Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wx5575
excelize
提交
891e5baa
excelize
项目概览
wx5575
/
excelize
与 Fork 源项目一致
Fork自
xuri / excelize
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
excelize
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
已验证
提交
891e5baa
编写于
1月 11, 2022
作者:
xurime
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ref #1096, reduce memory usage by about 50% for large data spreadsheet
上级
2245fccc
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
117 addition
and
41 deletion
+117
-41
cell.go
cell.go
+12
-2
cell_test.go
cell_test.go
+51
-3
excelize.go
excelize.go
+25
-24
file.go
file.go
+5
-0
rows.go
rows.go
+23
-12
templates.go
templates.go
+1
-0
未找到文件。
cell.go
浏览文件 @
891e5baa
...
...
@@ -375,8 +375,18 @@ func (f *File) sharedStringsLoader() (err error) {
if
path
,
ok
:=
f
.
tempFiles
.
Load
(
defaultXMLPathSharedStrings
);
ok
{
f
.
Pkg
.
Store
(
defaultXMLPathSharedStrings
,
f
.
readBytes
(
defaultXMLPathSharedStrings
))
f
.
tempFiles
.
Delete
(
defaultXMLPathSharedStrings
)
err
=
os
.
Remove
(
path
.
(
string
))
f
.
SharedStrings
,
f
.
sharedStringItemMap
=
nil
,
nil
if
err
=
os
.
Remove
(
path
.
(
string
));
err
!=
nil
{
return
}
f
.
SharedStrings
=
nil
}
if
f
.
sharedStringTemp
!=
nil
{
if
err
:=
f
.
sharedStringTemp
.
Close
();
err
!=
nil
{
return
err
}
f
.
tempFiles
.
Delete
(
defaultTempFileSST
)
f
.
sharedStringItem
,
err
=
nil
,
os
.
Remove
(
f
.
sharedStringTemp
.
Name
())
f
.
sharedStringTemp
=
nil
}
return
}
...
...
cell_test.go
浏览文件 @
891e5baa
...
...
@@ -2,6 +2,7 @@ package excelize
import
(
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
...
...
@@ -653,9 +654,12 @@ func TestFormattedValue2(t *testing.T) {
func
TestSharedStringsError
(
t
*
testing
.
T
)
{
f
,
err
:=
OpenFile
(
filepath
.
Join
(
"test"
,
"Book1.xlsx"
),
Options
{
UnzipXMLSizeLimit
:
128
})
assert
.
NoError
(
t
,
err
)
tempFile
,
ok
:=
f
.
tempFiles
.
Load
(
defaultXMLPathSharedStrings
)
assert
.
True
(
t
,
ok
)
f
.
tempFiles
.
Store
(
defaultXMLPathSharedStrings
,
""
)
assert
.
Equal
(
t
,
"1"
,
f
.
getFromStringItemMap
(
1
))
assert
.
Equal
(
t
,
"1"
,
f
.
getFromStringItem
(
1
))
// Cleanup undelete temporary files
assert
.
NoError
(
t
,
os
.
Remove
(
tempFile
.
(
string
)))
// Test reload the file error on set cell cell and rich text. The error message was different between macOS and Windows.
err
=
f
.
SetCellValue
(
"Sheet1"
,
"A19"
,
"A19"
)
assert
.
Error
(
t
,
err
)
...
...
@@ -663,6 +667,50 @@ func TestSharedStringsError(t *testing.T) {
f
.
tempFiles
.
Store
(
defaultXMLPathSharedStrings
,
""
)
err
=
f
.
SetCellRichText
(
"Sheet1"
,
"A19"
,
[]
RichTextRun
{})
assert
.
Error
(
t
,
err
)
assert
.
NoError
(
t
,
f
.
Close
())
f
,
err
=
OpenFile
(
filepath
.
Join
(
"test"
,
"Book1.xlsx"
),
Options
{
UnzipXMLSizeLimit
:
128
})
assert
.
NoError
(
t
,
err
)
rows
,
err
:=
f
.
Rows
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
const
maxUint16
=
1
<<
16
-
1
for
rows
.
Next
()
{
if
rows
.
CurrentRow
()
==
19
{
_
,
err
:=
rows
.
Columns
()
assert
.
NoError
(
t
,
err
)
// Test get cell value from string item with invalid offset
f
.
sharedStringItem
[
1
]
=
[]
uint
{
maxUint16
-
1
,
maxUint16
}
assert
.
Equal
(
t
,
"1"
,
f
.
getFromStringItem
(
1
))
break
}
}
assert
.
NoError
(
t
,
rows
.
Close
())
// Test shared string item temporary files has been closed before close the workbook
assert
.
NoError
(
t
,
f
.
sharedStringTemp
.
Close
())
assert
.
Error
(
t
,
f
.
Close
())
// Cleanup undelete temporary files
f
.
tempFiles
.
Range
(
func
(
k
,
v
interface
{})
bool
{
return
assert
.
NoError
(
t
,
os
.
Remove
(
v
.
(
string
)))
})
f
,
err
=
OpenFile
(
filepath
.
Join
(
"test"
,
"Book1.xlsx"
),
Options
{
UnzipXMLSizeLimit
:
128
})
assert
.
NoError
(
t
,
err
)
rows
,
err
=
f
.
Rows
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
for
rows
.
Next
()
{
if
rows
.
CurrentRow
()
==
19
{
_
,
err
:=
rows
.
Columns
()
assert
.
NoError
(
t
,
err
)
break
}
}
assert
.
NoError
(
t
,
rows
.
Close
())
assert
.
NoError
(
t
,
f
.
sharedStringTemp
.
Close
())
// Test shared string item temporary files has been closed before set the cell value
assert
.
Error
(
t
,
f
.
SetCellValue
(
"Sheet1"
,
"A1"
,
"A1"
))
assert
.
Error
(
t
,
f
.
Close
())
// Cleanup undelete temporary files
f
.
tempFiles
.
Range
(
func
(
k
,
v
interface
{})
bool
{
return
assert
.
NoError
(
t
,
os
.
Remove
(
v
.
(
string
)))
})
}
excelize.go
浏览文件 @
891e5baa
...
...
@@ -32,30 +32,31 @@ import (
// File define a populated spreadsheet file struct.
type
File
struct
{
sync
.
Mutex
options
*
Options
xmlAttr
map
[
string
][]
xml
.
Attr
checked
map
[
string
]
bool
sheetMap
map
[
string
]
string
streams
map
[
string
]
*
StreamWriter
tempFiles
sync
.
Map
CalcChain
*
xlsxCalcChain
Comments
map
[
string
]
*
xlsxComments
ContentTypes
*
xlsxTypes
Drawings
sync
.
Map
Path
string
SharedStrings
*
xlsxSST
sharedStringsMap
map
[
string
]
int
sharedStringItemMap
*
sync
.
Map
Sheet
sync
.
Map
SheetCount
int
Styles
*
xlsxStyleSheet
Theme
*
xlsxTheme
DecodeVMLDrawing
map
[
string
]
*
decodeVmlDrawing
VMLDrawing
map
[
string
]
*
vmlDrawing
WorkBook
*
xlsxWorkbook
Relationships
sync
.
Map
Pkg
sync
.
Map
CharsetReader
charsetTranscoderFn
options
*
Options
xmlAttr
map
[
string
][]
xml
.
Attr
checked
map
[
string
]
bool
sheetMap
map
[
string
]
string
streams
map
[
string
]
*
StreamWriter
tempFiles
sync
.
Map
CalcChain
*
xlsxCalcChain
Comments
map
[
string
]
*
xlsxComments
ContentTypes
*
xlsxTypes
Drawings
sync
.
Map
Path
string
SharedStrings
*
xlsxSST
sharedStringsMap
map
[
string
]
int
sharedStringItem
[][]
uint
sharedStringTemp
*
os
.
File
Sheet
sync
.
Map
SheetCount
int
Styles
*
xlsxStyleSheet
Theme
*
xlsxTheme
DecodeVMLDrawing
map
[
string
]
*
decodeVmlDrawing
VMLDrawing
map
[
string
]
*
vmlDrawing
WorkBook
*
xlsxWorkbook
Relationships
sync
.
Map
Pkg
sync
.
Map
CharsetReader
charsetTranscoderFn
}
type
charsetTranscoderFn
func
(
charset
string
,
input
io
.
Reader
)
(
rdr
io
.
Reader
,
err
error
)
...
...
file.go
浏览文件 @
891e5baa
...
...
@@ -85,6 +85,11 @@ func (f *File) SaveAs(name string, opt ...Options) error {
// Close closes and cleanup the open temporary file for the spreadsheet.
func
(
f
*
File
)
Close
()
error
{
var
err
error
if
f
.
sharedStringTemp
!=
nil
{
if
err
:=
f
.
sharedStringTemp
.
Close
();
err
!=
nil
{
return
err
}
}
f
.
tempFiles
.
Range
(
func
(
k
,
v
interface
{})
bool
{
if
err
=
os
.
Remove
(
v
.
(
string
));
err
!=
nil
{
return
false
...
...
rows.go
浏览文件 @
891e5baa
...
...
@@ -16,12 +16,12 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"math"
"math/big"
"os"
"strconv"
"sync"
"github.com/mohae/deepcopy"
)
...
...
@@ -280,23 +280,30 @@ func (f *File) Rows(sheet string) (*Rows, error) {
return
&
rows
,
nil
}
// getFromStringItem
Map build shared string item map
from system temporary
// getFromStringItem
build shared string item offset list
from system temporary
// file at one time, and return value by given to string index.
func
(
f
*
File
)
getFromStringItem
Map
(
index
int
)
string
{
if
f
.
sharedString
ItemMa
p
!=
nil
{
if
value
,
ok
:=
f
.
sharedStringItemMap
.
Load
(
index
);
ok
{
return
value
.
(
string
)
func
(
f
*
File
)
getFromStringItem
(
index
int
)
string
{
if
f
.
sharedString
Tem
p
!=
nil
{
if
len
(
f
.
sharedStringItem
)
<=
index
{
return
strconv
.
Itoa
(
index
)
}
return
strconv
.
Itoa
(
index
)
offsetRange
:=
f
.
sharedStringItem
[
index
]
buf
:=
make
([]
byte
,
offsetRange
[
1
]
-
offsetRange
[
0
])
if
_
,
err
:=
f
.
sharedStringTemp
.
ReadAt
(
buf
,
int64
(
offsetRange
[
0
]));
err
!=
nil
{
return
strconv
.
Itoa
(
index
)
}
return
string
(
buf
)
}
f
.
sharedStringItemMap
=
&
sync
.
Map
{}
needClose
,
decoder
,
tempFile
,
err
:=
f
.
xmlDecoder
(
defaultXMLPathSharedStrings
)
if
needClose
&&
err
==
nil
{
defer
tempFile
.
Close
()
}
f
.
sharedStringItem
=
[][]
uint
{}
f
.
sharedStringTemp
,
_
=
ioutil
.
TempFile
(
os
.
TempDir
(),
"excelize-"
)
f
.
tempFiles
.
Store
(
defaultTempFileSST
,
f
.
sharedStringTemp
.
Name
())
var
(
inElement
string
i
int
i
,
offset
u
int
)
for
{
token
,
_
:=
decoder
.
Token
()
...
...
@@ -309,12 +316,16 @@ func (f *File) getFromStringItemMap(index int) string {
if
inElement
==
"si"
{
si
:=
xlsxSI
{}
_
=
decoder
.
DecodeElement
(
&
si
,
&
xmlElement
)
f
.
sharedStringItemMap
.
Store
(
i
,
si
.
String
())
startIdx
:=
offset
n
,
_
:=
f
.
sharedStringTemp
.
WriteString
(
si
.
String
())
offset
+=
uint
(
n
)
f
.
sharedStringItem
=
append
(
f
.
sharedStringItem
,
[]
uint
{
startIdx
,
offset
})
i
++
}
}
}
return
f
.
getFromStringItem
Map
(
index
)
return
f
.
getFromStringItem
(
index
)
}
// xmlDecoder creates XML decoder by given path in the zip from memory data
...
...
@@ -454,7 +465,7 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
xlsxSI
:=
0
xlsxSI
,
_
=
strconv
.
Atoi
(
c
.
V
)
if
_
,
ok
:=
f
.
tempFiles
.
Load
(
defaultXMLPathSharedStrings
);
ok
{
return
f
.
formattedValue
(
c
.
S
,
f
.
getFromStringItem
Map
(
xlsxSI
),
raw
),
nil
return
f
.
formattedValue
(
c
.
S
,
f
.
getFromStringItem
(
xlsxSI
),
raw
),
nil
}
if
len
(
d
.
SI
)
>
xlsxSI
{
return
f
.
formattedValue
(
c
.
S
,
d
.
SI
[
xlsxSI
]
.
String
(),
raw
),
nil
...
...
templates.go
浏览文件 @
891e5baa
...
...
@@ -30,6 +30,7 @@ const (
defaultXMLPathSharedStrings
=
"xl/sharedStrings.xml"
defaultXMLPathStyles
=
"xl/styles.xml"
defaultXMLPathWorkbook
=
"xl/workbook.xml"
defaultTempFileSST
=
"sharedStrings"
)
const
templateDocpropsApp
=
`<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><TotalTime>0</TotalTime><Application>Go Excelize</Application></Properties>`
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录