Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xuri
excelize
提交
fe639faa
excelize
项目概览
xuri
/
excelize
通知
13
Star
2
Fork
4
代码
文件
提交
分支
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 搜索 >>
未验证
提交
fe639faa
编写于
11月 06, 2023
作者:
A
Anton Petrov
提交者:
GitHub
11月 06, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
This closes #1125, support update drawing objects on inserting/deleting columns/rows (#1127)
上级
f753e560
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
335 addition
and
100 deletion
+335
-100
adjust.go
adjust.go
+155
-21
adjust_test.go
adjust_test.go
+93
-12
picture.go
picture.go
+38
-57
picture_test.go
picture_test.go
+5
-3
xmlDecodeDrawing.go
xmlDecodeDrawing.go
+26
-7
xmlDrawing.go
xmlDrawing.go
+18
-0
未找到文件。
adjust.go
浏览文件 @
fe639faa
...
...
@@ -29,6 +29,28 @@ const (
rows
adjustDirection
=
true
)
// adjustHelperFunc defines functions to adjust helper.
var
adjustHelperFunc
=
[
6
]
func
(
*
File
,
*
xlsxWorksheet
,
string
,
adjustDirection
,
int
,
int
,
int
)
error
{
func
(
f
*
File
,
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
return
f
.
adjustTable
(
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
)
},
func
(
f
*
File
,
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
return
f
.
adjustMergeCells
(
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
)
},
func
(
f
*
File
,
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
return
f
.
adjustAutoFilter
(
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
)
},
func
(
f
*
File
,
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
return
f
.
adjustCalcChain
(
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
)
},
func
(
f
*
File
,
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
return
f
.
adjustVolatileDeps
(
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
)
},
func
(
f
*
File
,
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
return
f
.
adjustDrawings
(
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
)
},
}
// adjustHelper provides a function to adjust rows and columns dimensions,
// hyperlinks, merged cells and auto filter when inserting or deleting rows or
// columns.
...
...
@@ -56,23 +78,14 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
f
.
adjustHyperlinks
(
ws
,
sheet
,
dir
,
num
,
offset
)
ws
.
checkSheet
()
_
=
ws
.
checkRow
()
f
.
adjustTable
(
ws
,
sheet
,
dir
,
num
,
offset
)
if
err
=
f
.
adjustMergeCells
(
ws
,
dir
,
num
,
offset
);
err
!=
nil
{
return
err
}
if
err
=
f
.
adjustAutoFilter
(
ws
,
dir
,
num
,
offset
);
err
!=
nil
{
return
err
}
if
err
=
f
.
adjustCalcChain
(
dir
,
num
,
offset
,
sheetID
);
err
!=
nil
{
return
err
}
if
err
=
f
.
adjustVolatileDeps
(
dir
,
num
,
offset
,
sheetID
);
err
!=
nil
{
return
err
for
_
,
fn
:=
range
adjustHelperFunc
{
if
err
:=
fn
(
f
,
ws
,
sheet
,
dir
,
num
,
offset
,
sheetID
);
err
!=
nil
{
return
err
}
}
if
ws
.
MergeCells
!=
nil
&&
len
(
ws
.
MergeCells
.
Cells
)
==
0
{
ws
.
MergeCells
=
nil
}
return
nil
}
...
...
@@ -460,9 +473,9 @@ func (f *File) adjustHyperlinks(ws *xlsxWorksheet, sheet string, dir adjustDirec
// adjustTable provides a function to update the table when inserting or
// deleting rows or columns.
func
(
f
*
File
)
adjustTable
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
int
)
{
func
(
f
*
File
)
adjustTable
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
if
ws
.
TableParts
==
nil
||
len
(
ws
.
TableParts
.
TableParts
)
==
0
{
return
return
nil
}
for
idx
:=
0
;
idx
<
len
(
ws
.
TableParts
.
TableParts
);
idx
++
{
tbl
:=
ws
.
TableParts
.
TableParts
[
idx
]
...
...
@@ -475,11 +488,11 @@ func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDirection,
t
:=
xlsxTable
{}
if
err
:=
f
.
xmlNewDecoder
(
bytes
.
NewReader
(
namespaceStrictToTransitional
(
content
.
([]
byte
))))
.
Decode
(
&
t
);
err
!=
nil
&&
err
!=
io
.
EOF
{
return
return
nil
}
coordinates
,
err
:=
rangeRefToCoordinates
(
t
.
Ref
)
if
err
!=
nil
{
return
return
err
}
// Remove the table when deleting the header row of the table
if
dir
==
rows
&&
num
==
coordinates
[
0
]
&&
offset
==
-
1
{
...
...
@@ -506,11 +519,12 @@ func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDirection,
table
,
_
:=
xml
.
Marshal
(
t
)
f
.
saveFileList
(
tableXML
,
table
)
}
return
nil
}
// adjustAutoFilter provides a function to update the auto filter when
// inserting or deleting rows or columns.
func
(
f
*
File
)
adjustAutoFilter
(
ws
*
xlsxWorksheet
,
dir
adjustDirection
,
num
,
offset
int
)
error
{
func
(
f
*
File
)
adjustAutoFilter
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
if
ws
.
AutoFilter
==
nil
{
return
nil
}
...
...
@@ -563,7 +577,7 @@ func (f *File) adjustAutoFilterHelper(dir adjustDirection, coordinates []int, nu
// adjustMergeCells provides a function to update merged cells when inserting
// or deleting rows or columns.
func
(
f
*
File
)
adjustMergeCells
(
ws
*
xlsxWorksheet
,
dir
adjustDirection
,
num
,
offset
int
)
error
{
func
(
f
*
File
)
adjustMergeCells
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
if
ws
.
MergeCells
==
nil
{
return
nil
}
...
...
@@ -657,7 +671,7 @@ func adjustCellName(cell string, dir adjustDirection, c, r, offset int) (string,
// adjustCalcChain provides a function to update the calculation chain when
// inserting or deleting rows or columns.
func
(
f
*
File
)
adjustCalcChain
(
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
func
(
f
*
File
)
adjustCalcChain
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
if
f
.
CalcChain
==
nil
{
return
nil
}
...
...
@@ -728,7 +742,7 @@ func (vt *xlsxVolTypes) adjustVolatileDepsTopic(cell string, dir adjustDirection
// adjustVolatileDeps updates the volatile dependencies when inserting or
// deleting rows or columns.
func
(
f
*
File
)
adjustVolatileDeps
(
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
func
(
f
*
File
)
adjustVolatileDeps
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
volTypes
,
err
:=
f
.
volatileDepsReader
()
if
err
!=
nil
||
volTypes
==
nil
{
return
err
...
...
@@ -750,3 +764,123 @@ func (f *File) adjustVolatileDeps(dir adjustDirection, num, offset, sheetID int)
}
return
nil
}
// adjustDrawings updates the starting anchor of the two cell anchor pictures
// and charts object when inserting or deleting rows or columns.
func
(
from
*
xlsxFrom
)
adjustDrawings
(
dir
adjustDirection
,
num
,
offset
int
,
editAs
string
)
(
bool
,
error
)
{
var
ok
bool
if
dir
==
columns
&&
from
.
Col
+
1
>=
num
&&
from
.
Col
+
offset
>=
0
{
if
from
.
Col
+
offset
>=
MaxColumns
{
return
false
,
ErrColumnNumber
}
from
.
Col
+=
offset
ok
=
editAs
==
"oneCell"
}
if
dir
==
rows
&&
from
.
Row
+
1
>=
num
&&
from
.
Row
+
offset
>=
0
{
if
from
.
Row
+
offset
>=
TotalRows
{
return
false
,
ErrMaxRows
}
from
.
Row
+=
offset
ok
=
editAs
==
"oneCell"
}
return
ok
,
nil
}
// adjustDrawings updates the ending anchor of the two cell anchor pictures
// and charts object when inserting or deleting rows or columns.
func
(
to
*
xlsxTo
)
adjustDrawings
(
dir
adjustDirection
,
num
,
offset
int
,
editAs
string
,
ok
bool
)
error
{
if
dir
==
columns
&&
to
.
Col
+
1
>=
num
&&
to
.
Col
+
offset
>=
0
&&
ok
{
if
to
.
Col
+
offset
>=
MaxColumns
{
return
ErrColumnNumber
}
to
.
Col
+=
offset
}
if
dir
==
rows
&&
to
.
Row
+
1
>=
num
&&
to
.
Row
+
offset
>=
0
&&
ok
{
if
to
.
Row
+
offset
>=
TotalRows
{
return
ErrMaxRows
}
to
.
Row
+=
offset
}
return
nil
}
// adjustDrawings updates the two cell anchor pictures and charts object when
// inserting or deleting rows or columns.
func
(
a
*
xdrCellAnchor
)
adjustDrawings
(
dir
adjustDirection
,
num
,
offset
int
)
error
{
editAs
:=
a
.
EditAs
if
a
.
From
==
nil
||
a
.
To
==
nil
||
editAs
==
"absolute"
{
return
nil
}
ok
,
err
:=
a
.
From
.
adjustDrawings
(
dir
,
num
,
offset
,
editAs
)
if
err
!=
nil
{
return
err
}
return
a
.
To
.
adjustDrawings
(
dir
,
num
,
offset
,
editAs
,
ok
||
editAs
==
""
)
}
// adjustDrawings updates the existing two cell anchor pictures and charts
// object when inserting or deleting rows or columns.
func
(
a
*
xlsxCellAnchorPos
)
adjustDrawings
(
dir
adjustDirection
,
num
,
offset
int
,
editAs
string
)
error
{
if
a
.
From
==
nil
||
a
.
To
==
nil
||
editAs
==
"absolute"
{
return
nil
}
ok
,
err
:=
a
.
From
.
adjustDrawings
(
dir
,
num
,
offset
,
editAs
)
if
err
!=
nil
{
return
err
}
return
a
.
To
.
adjustDrawings
(
dir
,
num
,
offset
,
editAs
,
ok
||
editAs
==
""
)
}
// adjustDrawings updates the pictures and charts object when inserting or
// deleting rows or columns.
func
(
f
*
File
)
adjustDrawings
(
ws
*
xlsxWorksheet
,
sheet
string
,
dir
adjustDirection
,
num
,
offset
,
sheetID
int
)
error
{
if
ws
.
Drawing
==
nil
{
return
nil
}
target
:=
f
.
getSheetRelationshipsTargetByID
(
sheet
,
ws
.
Drawing
.
RID
)
drawingXML
:=
strings
.
TrimPrefix
(
strings
.
ReplaceAll
(
target
,
".."
,
"xl"
),
"/"
)
var
(
err
error
wsDr
*
xlsxWsDr
)
if
wsDr
,
_
,
err
=
f
.
drawingParser
(
drawingXML
);
err
!=
nil
{
return
err
}
anchorCb
:=
func
(
a
*
xdrCellAnchor
)
error
{
if
a
.
GraphicFrame
==
""
{
return
a
.
adjustDrawings
(
dir
,
num
,
offset
)
}
deCellAnchor
:=
decodeCellAnchor
{}
deCellAnchorPos
:=
decodeCellAnchorPos
{}
_
=
f
.
xmlNewDecoder
(
strings
.
NewReader
(
"<decodeCellAnchor>"
+
a
.
GraphicFrame
+
"</decodeCellAnchor>"
))
.
Decode
(
&
deCellAnchor
)
_
=
f
.
xmlNewDecoder
(
strings
.
NewReader
(
"<decodeCellAnchorPos>"
+
a
.
GraphicFrame
+
"</decodeCellAnchorPos>"
))
.
Decode
(
&
deCellAnchorPos
)
xlsxCellAnchorPos
:=
xlsxCellAnchorPos
(
deCellAnchorPos
)
for
i
:=
0
;
i
<
len
(
xlsxCellAnchorPos
.
AlternateContent
);
i
++
{
xlsxCellAnchorPos
.
AlternateContent
[
i
]
.
XMLNSMC
=
SourceRelationshipCompatibility
.
Value
}
if
deCellAnchor
.
From
!=
nil
{
xlsxCellAnchorPos
.
From
=
&
xlsxFrom
{
Col
:
deCellAnchor
.
From
.
Col
,
ColOff
:
deCellAnchor
.
From
.
ColOff
,
Row
:
deCellAnchor
.
From
.
Row
,
RowOff
:
deCellAnchor
.
From
.
RowOff
,
}
}
if
deCellAnchor
.
To
!=
nil
{
xlsxCellAnchorPos
.
To
=
&
xlsxTo
{
Col
:
deCellAnchor
.
To
.
Col
,
ColOff
:
deCellAnchor
.
To
.
ColOff
,
Row
:
deCellAnchor
.
To
.
Row
,
RowOff
:
deCellAnchor
.
To
.
RowOff
,
}
}
if
err
=
xlsxCellAnchorPos
.
adjustDrawings
(
dir
,
num
,
offset
,
a
.
EditAs
);
err
!=
nil
{
return
err
}
cellAnchor
,
_
:=
xml
.
Marshal
(
xlsxCellAnchorPos
)
a
.
GraphicFrame
=
strings
.
TrimSuffix
(
strings
.
TrimPrefix
(
string
(
cellAnchor
),
"<xlsxCellAnchorPos>"
),
"</xlsxCellAnchorPos>"
)
return
err
}
for
_
,
anchor
:=
range
wsDr
.
TwoCellAnchor
{
if
err
=
anchorCb
(
anchor
);
err
!=
nil
{
return
err
}
}
return
nil
}
adjust_test.go
浏览文件 @
fe639faa
package
excelize
import
(
"encoding/xml"
"fmt"
"path/filepath"
"testing"
_
"image/jpeg"
"github.com/stretchr/testify/assert"
)
...
...
@@ -19,7 +22,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
},
},
},
rows
,
0
,
0
),
newCellNameToCoordinatesError
(
"A"
,
newInvalidCellNameError
(
"A"
)))
},
"Sheet1"
,
rows
,
0
,
0
,
1
),
newCellNameToCoordinatesError
(
"A"
,
newInvalidCellNameError
(
"A"
)))
assert
.
Equal
(
t
,
f
.
adjustMergeCells
(
&
xlsxWorksheet
{
MergeCells
:
&
xlsxMergeCells
{
Cells
:
[]
*
xlsxMergeCell
{
...
...
@@ -28,7 +31,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
},
},
},
rows
,
0
,
0
),
newCellNameToCoordinatesError
(
"B"
,
newInvalidCellNameError
(
"B"
)))
},
"Sheet1"
,
rows
,
0
,
0
,
1
),
newCellNameToCoordinatesError
(
"B"
,
newInvalidCellNameError
(
"B"
)))
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
&
xlsxWorksheet
{
MergeCells
:
&
xlsxMergeCells
{
Cells
:
[]
*
xlsxMergeCell
{
...
...
@@ -37,7 +40,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
},
},
},
rows
,
1
,
-
1
))
},
"Sheet1"
,
rows
,
1
,
-
1
,
1
))
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
&
xlsxWorksheet
{
MergeCells
:
&
xlsxMergeCells
{
Cells
:
[]
*
xlsxMergeCell
{
...
...
@@ -46,7 +49,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
},
},
},
columns
,
1
,
-
1
))
},
"Sheet1"
,
columns
,
1
,
-
1
,
1
))
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
&
xlsxWorksheet
{
MergeCells
:
&
xlsxMergeCells
{
Cells
:
[]
*
xlsxMergeCell
{
...
...
@@ -55,7 +58,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
},
},
},
columns
,
1
,
-
1
))
},
"Sheet1"
,
columns
,
1
,
-
1
,
1
))
// Test adjust merge cells
var
cases
[]
struct
{
...
...
@@ -134,7 +137,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
}
for
_
,
c
:=
range
cases
{
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
c
.
ws
,
c
.
dir
,
c
.
num
,
1
))
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
c
.
ws
,
"Sheet1"
,
c
.
dir
,
c
.
num
,
1
,
1
))
assert
.
Equal
(
t
,
c
.
expect
,
c
.
ws
.
MergeCells
.
Cells
[
0
]
.
Ref
,
c
.
label
)
assert
.
Equal
(
t
,
c
.
expectRect
,
c
.
ws
.
MergeCells
.
Cells
[
0
]
.
rect
,
c
.
label
)
}
...
...
@@ -223,7 +226,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
}
for
_
,
c
:=
range
cases
{
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
c
.
ws
,
c
.
dir
,
c
.
num
,
-
1
))
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
c
.
ws
,
"Sheet1"
,
c
.
dir
,
c
.
num
,
-
1
,
1
))
assert
.
Equal
(
t
,
c
.
expect
,
c
.
ws
.
MergeCells
.
Cells
[
0
]
.
Ref
,
c
.
label
)
}
...
...
@@ -271,7 +274,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
}
for
_
,
c
:=
range
cases
{
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
c
.
ws
,
c
.
dir
,
c
.
num
,
-
1
))
assert
.
NoError
(
t
,
f
.
adjustMergeCells
(
c
.
ws
,
"Sheet1"
,
c
.
dir
,
c
.
num
,
-
1
,
1
))
assert
.
Len
(
t
,
c
.
ws
.
MergeCells
.
Cells
,
0
,
c
.
label
)
}
...
...
@@ -291,18 +294,18 @@ func TestAdjustAutoFilter(t *testing.T) {
AutoFilter
:
&
xlsxAutoFilter
{
Ref
:
"A1:A3"
,
},
},
rows
,
1
,
-
1
))
},
"Sheet1"
,
rows
,
1
,
-
1
,
1
))
// Test adjustAutoFilter with illegal cell reference
assert
.
Equal
(
t
,
f
.
adjustAutoFilter
(
&
xlsxWorksheet
{
AutoFilter
:
&
xlsxAutoFilter
{
Ref
:
"A:B1"
,
},
},
rows
,
0
,
0
),
newCellNameToCoordinatesError
(
"A"
,
newInvalidCellNameError
(
"A"
)))
},
"Sheet1"
,
rows
,
0
,
0
,
1
),
newCellNameToCoordinatesError
(
"A"
,
newInvalidCellNameError
(
"A"
)))
assert
.
Equal
(
t
,
f
.
adjustAutoFilter
(
&
xlsxWorksheet
{
AutoFilter
:
&
xlsxAutoFilter
{
Ref
:
"A1:B"
,
},
},
rows
,
0
,
0
),
newCellNameToCoordinatesError
(
"B"
,
newInvalidCellNameError
(
"B"
)))
},
"Sheet1"
,
rows
,
0
,
0
,
1
),
newCellNameToCoordinatesError
(
"B"
,
newInvalidCellNameError
(
"B"
)))
}
func
TestAdjustTable
(
t
*
testing
.
T
)
{
...
...
@@ -334,7 +337,7 @@ func TestAdjustTable(t *testing.T) {
assert
.
NoError
(
t
,
f
.
RemoveRow
(
sheetName
,
1
))
// Test adjust table with invalid table range reference
f
.
Pkg
.
Store
(
"xl/tables/table1.xml"
,
[]
byte
(
`<table ref="-" />`
))
assert
.
NoError
(
t
,
f
.
RemoveRow
(
sheetName
,
1
))
assert
.
Equal
(
t
,
ErrParameterInvalid
,
f
.
RemoveRow
(
sheetName
,
1
))
}
func
TestAdjustHelper
(
t
*
testing
.
T
)
{
...
...
@@ -947,3 +950,81 @@ func TestAdjustVolatileDeps(t *testing.T) {
assert
.
Equal
(
t
,
newCellNameToCoordinatesError
(
"A"
,
newInvalidCellNameError
(
"A"
)),
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
))
f
.
volatileDepsWriter
()
}
func
TestAdjustDrawings
(
t
*
testing
.
T
)
{
f
:=
NewFile
()
// Test add pictures to sheet with positioning
assert
.
NoError
(
t
,
f
.
AddPicture
(
"Sheet1"
,
"B2"
,
filepath
.
Join
(
"test"
,
"images"
,
"excel.jpg"
),
nil
))
assert
.
NoError
(
t
,
f
.
AddPicture
(
"Sheet1"
,
"B11"
,
filepath
.
Join
(
"test"
,
"images"
,
"excel.jpg"
),
&
GraphicOptions
{
Positioning
:
"oneCell"
}))
assert
.
NoError
(
t
,
f
.
AddPicture
(
"Sheet1"
,
"B21"
,
filepath
.
Join
(
"test"
,
"images"
,
"excel.jpg"
),
&
GraphicOptions
{
Positioning
:
"absolute"
}))
// Test adjust pictures on inserting columns and rows
assert
.
NoError
(
t
,
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
))
assert
.
NoError
(
t
,
f
.
InsertRows
(
"Sheet1"
,
1
,
1
))
assert
.
NoError
(
t
,
f
.
InsertCols
(
"Sheet1"
,
"C"
,
1
))
assert
.
NoError
(
t
,
f
.
InsertRows
(
"Sheet1"
,
5
,
1
))
assert
.
NoError
(
t
,
f
.
InsertRows
(
"Sheet1"
,
15
,
1
))
cells
,
err
:=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
string
{
"D3"
,
"D13"
,
"B21"
},
cells
)
wb
:=
filepath
.
Join
(
"test"
,
"TestAdjustDrawings.xlsx"
)
assert
.
NoError
(
t
,
f
.
SaveAs
(
wb
))
// Test adjust pictures on deleting columns and rows
assert
.
NoError
(
t
,
f
.
RemoveCol
(
"Sheet1"
,
"A"
))
assert
.
NoError
(
t
,
f
.
RemoveRow
(
"Sheet1"
,
1
))
cells
,
err
=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
string
{
"C2"
,
"C12"
,
"B21"
},
cells
)
// Test adjust existing pictures on inserting columns and rows
f
,
err
=
OpenFile
(
wb
)
assert
.
NoError
(
t
,
err
)
assert
.
NoError
(
t
,
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
))
assert
.
NoError
(
t
,
f
.
InsertRows
(
"Sheet1"
,
1
,
1
))
assert
.
NoError
(
t
,
f
.
InsertCols
(
"Sheet1"
,
"D"
,
1
))
assert
.
NoError
(
t
,
f
.
InsertRows
(
"Sheet1"
,
5
,
1
))
assert
.
NoError
(
t
,
f
.
InsertRows
(
"Sheet1"
,
16
,
1
))
cells
,
err
=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
string
{
"F4"
,
"F15"
,
"B21"
},
cells
)
// Test adjust drawings with unsupported charset
f
,
err
=
OpenFile
(
wb
)
assert
.
NoError
(
t
,
err
)
f
.
Pkg
.
Store
(
"xl/drawings/drawing1.xml"
,
MacintoshCyrillicCharset
)
assert
.
EqualError
(
t
,
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
),
"XML syntax error on line 1: invalid UTF-8"
)
errors
:=
[]
error
{
ErrColumnNumber
,
ErrColumnNumber
,
ErrMaxRows
,
ErrMaxRows
}
cells
=
[]
string
{
"XFD1"
,
"XFB1"
}
for
i
,
cell
:=
range
cells
{
f
=
NewFile
()
assert
.
NoError
(
t
,
f
.
AddPicture
(
"Sheet1"
,
cell
,
filepath
.
Join
(
"test"
,
"images"
,
"excel.jpg"
),
nil
))
assert
.
Equal
(
t
,
errors
[
i
],
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
))
assert
.
NoError
(
t
,
f
.
SaveAs
(
wb
))
f
,
err
=
OpenFile
(
wb
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
errors
[
i
],
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
))
}
errors
=
[]
error
{
ErrMaxRows
,
ErrMaxRows
}
cells
=
[]
string
{
"A1048576"
,
"A1048570"
}
for
i
,
cell
:=
range
cells
{
f
=
NewFile
()
assert
.
NoError
(
t
,
f
.
AddPicture
(
"Sheet1"
,
cell
,
filepath
.
Join
(
"test"
,
"images"
,
"excel.jpg"
),
nil
))
assert
.
Equal
(
t
,
errors
[
i
],
f
.
InsertRows
(
"Sheet1"
,
1
,
1
))
assert
.
NoError
(
t
,
f
.
SaveAs
(
wb
))
f
,
err
=
OpenFile
(
wb
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
errors
[
i
],
f
.
InsertRows
(
"Sheet1"
,
1
,
1
))
}
a
:=
xdrCellAnchor
{}
assert
.
NoError
(
t
,
a
.
adjustDrawings
(
columns
,
0
,
0
))
p
:=
xlsxCellAnchorPos
{}
assert
.
NoError
(
t
,
p
.
adjustDrawings
(
columns
,
0
,
0
,
""
))
f
,
err
=
OpenFile
(
wb
)
assert
.
NoError
(
t
,
err
)
f
.
Pkg
.
Store
(
"xl/drawings/drawing1.xml"
,
[]
byte
(
xml
.
Header
+
`<wsDr xmlns="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"><twoCellAnchor><from><col>0</col><colOff>0</colOff><row>0</row><rowOff>0</rowOff></from><to><col>1</col><colOff>0</colOff><row>1</row><rowOff>0</rowOff></to><mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"></mc:AlternateContent><clientData/></twoCellAnchor></wsDr>`
))
assert
.
NoError
(
t
,
f
.
InsertCols
(
"Sheet1"
,
"A"
,
1
))
}
picture.go
浏览文件 @
fe639faa
...
...
@@ -15,7 +15,6 @@ import (
"bytes"
"encoding/xml"
"image"
"io"
"os"
"path"
"path/filepath"
...
...
@@ -471,7 +470,7 @@ func (f *File) GetPictures(sheet, cell string) ([]Picture, error) {
return
nil
,
err
}
target
:=
f
.
getSheetRelationshipsTargetByID
(
sheet
,
ws
.
Drawing
.
RID
)
drawingXML
:=
strings
.
ReplaceAll
(
target
,
".."
,
"xl
"
)
drawingXML
:=
strings
.
TrimPrefix
(
strings
.
ReplaceAll
(
target
,
".."
,
"xl"
),
"/
"
)
drawingRelationships
:=
strings
.
ReplaceAll
(
strings
.
ReplaceAll
(
target
,
"../drawings"
,
"xl/drawings/_rels"
),
".xml"
,
".xml.rels"
)
...
...
@@ -492,7 +491,7 @@ func (f *File) GetPictureCells(sheet string) ([]string, error) {
return
nil
,
err
}
target
:=
f
.
getSheetRelationshipsTargetByID
(
sheet
,
ws
.
Drawing
.
RID
)
drawingXML
:=
strings
.
ReplaceAll
(
target
,
".."
,
"xl
"
)
drawingXML
:=
strings
.
TrimPrefix
(
strings
.
ReplaceAll
(
target
,
".."
,
"xl"
),
"/
"
)
drawingRelationships
:=
strings
.
ReplaceAll
(
strings
.
ReplaceAll
(
target
,
"../drawings"
,
"xl/drawings/_rels"
),
".xml"
,
".xml.rels"
)
...
...
@@ -553,15 +552,15 @@ func (f *File) DeletePicture(sheet, cell string) error {
// getPicture provides a function to get picture base name and raw content
// embed in spreadsheet by given coordinates and drawing relationships.
func
(
f
*
File
)
getPicture
(
row
,
col
int
,
drawingXML
,
drawingRelationships
string
)
(
pics
[]
Picture
,
err
error
)
{
var
(
deWsDr
=
new
(
decodeWsDr
)
wsDr
*
xlsxWsDr
)
var
wsDr
*
xlsxWsDr
if
wsDr
,
_
,
err
=
f
.
drawingParser
(
drawingXML
);
err
!=
nil
{
return
}
anchorCond
:=
func
(
a
*
xdrCellAnchor
)
bool
{
return
a
.
From
.
Col
==
col
&&
a
.
From
.
Row
==
row
}
anchorCb
:=
func
(
a
*
xdrCellAnchor
,
r
*
xlsxRelationship
)
{
wsDr
.
mu
.
Lock
()
defer
wsDr
.
mu
.
Unlock
()
cond
:=
func
(
from
*
xlsxFrom
)
bool
{
return
from
.
Col
==
col
&&
from
.
Row
==
row
}
cond2
:=
func
(
from
*
decodeFrom
)
bool
{
return
from
.
Col
==
col
&&
from
.
Row
==
row
}
cb
:=
func
(
a
*
xdrCellAnchor
,
r
*
xlsxRelationship
)
{
pic
:=
Picture
{
Extension
:
filepath
.
Ext
(
r
.
Target
),
Format
:
&
GraphicOptions
{}}
if
buffer
,
_
:=
f
.
Pkg
.
Load
(
strings
.
ReplaceAll
(
r
.
Target
,
".."
,
"xl"
));
buffer
!=
nil
{
pic
.
File
=
buffer
.
([]
byte
)
...
...
@@ -569,14 +568,7 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
pics
=
append
(
pics
,
pic
)
}
}
f
.
extractCellAnchor
(
drawingRelationships
,
wsDr
,
anchorCond
,
anchorCb
)
if
err
=
f
.
xmlNewDecoder
(
bytes
.
NewReader
(
namespaceStrictToTransitional
(
f
.
readXML
(
drawingXML
))))
.
Decode
(
deWsDr
);
err
!=
nil
&&
err
!=
io
.
EOF
{
return
}
err
=
nil
decodeAnchorCond
:=
func
(
a
*
decodeCellAnchor
)
bool
{
return
a
.
From
.
Col
==
col
&&
a
.
From
.
Row
==
row
}
decodeAnchorCb
:=
func
(
a
*
decodeCellAnchor
,
r
*
xlsxRelationship
)
{
cb2
:=
func
(
a
*
decodeCellAnchor
,
r
*
xlsxRelationship
)
{
pic
:=
Picture
{
Extension
:
filepath
.
Ext
(
r
.
Target
),
Format
:
&
GraphicOptions
{}}
if
buffer
,
_
:=
f
.
Pkg
.
Load
(
strings
.
ReplaceAll
(
r
.
Target
,
".."
,
"xl"
));
buffer
!=
nil
{
pic
.
File
=
buffer
.
([]
byte
)
...
...
@@ -584,11 +576,11 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
pics
=
append
(
pics
,
pic
)
}
}
for
_
,
anchor
:=
range
deW
sDr
.
TwoCellAnchor
{
f
.
extract
DecodeCellAnchor
(
anchor
,
drawingRelationships
,
decodeAnchorCond
,
decodeAnchorCb
)
for
_
,
anchor
:=
range
w
sDr
.
TwoCellAnchor
{
f
.
extract
CellAnchor
(
anchor
,
drawingRelationships
,
cond
,
cb
,
cond2
,
cb2
)
}
for
_
,
anchor
:=
range
deW
sDr
.
OneCellAnchor
{
f
.
extract
DecodeCellAnchor
(
anchor
,
drawingRelationships
,
decodeAnchorCond
,
decodeAnchorCb
)
for
_
,
anchor
:=
range
w
sDr
.
OneCellAnchor
{
f
.
extract
CellAnchor
(
anchor
,
drawingRelationships
,
cond
,
cb
,
cond2
,
cb2
)
}
return
}
...
...
@@ -596,18 +588,14 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
// extractCellAnchor extract drawing object from cell anchor by giving drawing
// cell anchor, drawing relationships part path, conditional and callback
// function.
func
(
f
*
File
)
extractCellAnchor
(
drawingRelationships
string
,
wsDr
*
xlsxWsDr
,
cond
func
(
anchor
*
xdrCellAnchor
)
bool
,
cb
func
(
anchor
*
xdrCellAnchor
,
rels
*
xlsxRelationship
),
func
(
f
*
File
)
extractCellAnchor
(
anchor
*
xdrCellAnchor
,
drawingRelationships
string
,
cond
func
(
from
*
xlsxFrom
)
bool
,
cb
func
(
anchor
*
xdrCellAnchor
,
rels
*
xlsxRelationship
),
cond2
func
(
from
*
decodeFrom
)
bool
,
cb2
func
(
anchor
*
decodeCellAnchor
,
rels
*
xlsxRelationship
),
)
{
var
(
anchor
*
xdrCellAnchor
drawRel
*
xlsxRelationship
)
wsDr
.
mu
.
Lock
()
defer
wsDr
.
mu
.
Unlock
()
for
_
,
anchor
=
range
wsDr
.
TwoCellAnchor
{
var
drawRel
*
xlsxRelationship
if
anchor
.
GraphicFrame
==
""
{
if
anchor
.
From
!=
nil
&&
anchor
.
Pic
!=
nil
{
if
cond
(
anchor
)
{
if
cond
(
anchor
.
From
)
{
if
drawRel
=
f
.
getDrawingRelationships
(
drawingRelationships
,
anchor
.
Pic
.
BlipFill
.
Blip
.
Embed
);
drawRel
!=
nil
{
if
_
,
ok
:=
supportedImageTypes
[
strings
.
ToLower
(
filepath
.
Ext
(
drawRel
.
Target
))];
ok
{
...
...
@@ -616,25 +604,24 @@ func (f *File) extractCellAnchor(drawingRelationships string, wsDr *xlsxWsDr,
}
}
}
return
}
f
.
extractDecodeCellAnchor
(
anchor
,
drawingRelationships
,
cond2
,
cb2
)
}
// extractDecodeCellAnchor extract drawing object from cell anchor by giving
// decoded drawing cell anchor, drawing relationships part path, conditional and
// callback function.
func
(
f
*
File
)
extractDecodeCellAnchor
(
anchor
*
decode
CellAnchor
,
drawingRelationships
string
,
cond
func
(
anchor
*
decodeCellAnchor
)
bool
,
cb
func
(
anchor
*
decodeCellAnchor
,
rels
*
xlsxRelationship
),
func
(
f
*
File
)
extractDecodeCellAnchor
(
anchor
*
xdr
CellAnchor
,
drawingRelationships
string
,
cond
func
(
from
*
decodeFrom
)
bool
,
cb
func
(
anchor
*
decodeCellAnchor
,
rels
*
xlsxRelationship
),
)
{
var
(
drawRel
*
xlsxRelationship
deCellAnchor
=
new
(
decodeCellAnchor
)
)
if
err
:=
f
.
xmlNewDecoder
(
strings
.
NewReader
(
"<decodeCellAnchor>"
+
anchor
.
Content
+
"</decodeCellAnchor>"
))
.
Decode
(
deCellAnchor
);
err
!=
nil
&&
err
!=
io
.
EOF
{
return
}
_
=
f
.
xmlNewDecoder
(
strings
.
NewReader
(
"<decodeCellAnchor>"
+
anchor
.
GraphicFrame
+
"</decodeCellAnchor>"
))
.
Decode
(
&
deCellAnchor
)
if
deCellAnchor
.
From
!=
nil
&&
deCellAnchor
.
Pic
!=
nil
{
if
cond
(
deCellAnchor
)
{
if
cond
(
deCellAnchor
.
From
)
{
drawRel
=
f
.
getDrawingRelationships
(
drawingRelationships
,
deCellAnchor
.
Pic
.
BlipFill
.
Blip
.
Embed
)
if
_
,
ok
:=
supportedImageTypes
[
strings
.
ToLower
(
filepath
.
Ext
(
drawRel
.
Target
))];
ok
{
cb
(
deCellAnchor
,
drawRel
)
...
...
@@ -720,42 +707,36 @@ func (f *File) drawingResize(sheet, cell string, width, height float64, opts *Gr
// worksheet by given drawing part path and drawing relationships path.
func
(
f
*
File
)
getPictureCells
(
drawingXML
,
drawingRelationships
string
)
([]
string
,
error
)
{
var
(
cells
[]
string
err
error
deWsDr
*
decodeWsDr
wsDr
*
xlsxWsDr
cells
[]
string
err
error
wsDr
*
xlsxWsDr
)
if
wsDr
,
_
,
err
=
f
.
drawingParser
(
drawingXML
);
err
!=
nil
{
return
cells
,
err
}
anchorCond
:=
func
(
a
*
xdrCellAnchor
)
bool
{
return
true
}
anchorCb
:=
func
(
a
*
xdrCellAnchor
,
r
*
xlsxRelationship
)
{
wsDr
.
mu
.
Lock
()
defer
wsDr
.
mu
.
Unlock
()
cond
:=
func
(
from
*
xlsxFrom
)
bool
{
return
true
}
cond2
:=
func
(
from
*
decodeFrom
)
bool
{
return
true
}
cb
:=
func
(
a
*
xdrCellAnchor
,
r
*
xlsxRelationship
)
{
if
_
,
ok
:=
f
.
Pkg
.
Load
(
strings
.
ReplaceAll
(
r
.
Target
,
".."
,
"xl"
));
ok
{
if
cell
,
err
:=
CoordinatesToCellName
(
a
.
From
.
Col
+
1
,
a
.
From
.
Row
+
1
);
err
==
nil
&&
inStrSlice
(
cells
,
cell
,
true
)
==
-
1
{
cells
=
append
(
cells
,
cell
)
}
}
}
f
.
extractCellAnchor
(
drawingRelationships
,
wsDr
,
anchorCond
,
anchorCb
)
deWsDr
=
new
(
decodeWsDr
)
if
err
=
f
.
xmlNewDecoder
(
bytes
.
NewReader
(
namespaceStrictToTransitional
(
f
.
readXML
(
drawingXML
))))
.
Decode
(
deWsDr
);
err
!=
nil
&&
err
!=
io
.
EOF
{
return
cells
,
err
}
err
=
nil
decodeAnchorCond
:=
func
(
a
*
decodeCellAnchor
)
bool
{
return
true
}
decodeAnchorCb
:=
func
(
a
*
decodeCellAnchor
,
r
*
xlsxRelationship
)
{
cb2
:=
func
(
a
*
decodeCellAnchor
,
r
*
xlsxRelationship
)
{
if
_
,
ok
:=
f
.
Pkg
.
Load
(
strings
.
ReplaceAll
(
r
.
Target
,
".."
,
"xl"
));
ok
{
if
cell
,
err
:=
CoordinatesToCellName
(
a
.
From
.
Col
+
1
,
a
.
From
.
Row
+
1
);
err
==
nil
&&
inStrSlice
(
cells
,
cell
,
true
)
==
-
1
{
cells
=
append
(
cells
,
cell
)
}
}
}
for
_
,
anchor
:=
range
deW
sDr
.
TwoCellAnchor
{
f
.
extract
DecodeCellAnchor
(
anchor
,
drawingRelationships
,
decodeAnchorCond
,
decodeAnchorCb
)
for
_
,
anchor
:=
range
w
sDr
.
TwoCellAnchor
{
f
.
extract
CellAnchor
(
anchor
,
drawingRelationships
,
cond
,
cb
,
cond2
,
cb2
)
}
for
_
,
anchor
:=
range
deW
sDr
.
OneCellAnchor
{
f
.
extract
DecodeCellAnchor
(
anchor
,
drawingRelationships
,
decodeAnchorCond
,
decodeAnchorCb
)
for
_
,
anchor
:=
range
w
sDr
.
OneCellAnchor
{
f
.
extract
CellAnchor
(
anchor
,
drawingRelationships
,
cond
,
cb
,
cond2
,
cb2
)
}
return
cells
,
err
}
picture_test.go
浏览文件 @
fe639faa
...
...
@@ -81,7 +81,7 @@ func TestAddPicture(t *testing.T) {
// Test get picture cells
cells
,
err
:=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
string
{
"
A30"
,
"F21
"
,
"B30"
,
"Q1"
,
"Q8"
,
"Q15"
,
"Q22"
,
"Q28"
},
cells
)
assert
.
Equal
(
t
,
[]
string
{
"
F21"
,
"A30
"
,
"B30"
,
"Q1"
,
"Q8"
,
"Q15"
,
"Q22"
,
"Q28"
},
cells
)
assert
.
NoError
(
t
,
f
.
Close
())
f
,
err
=
OpenFile
(
filepath
.
Join
(
"test"
,
"TestAddPicture1.xlsx"
))
...
...
@@ -92,6 +92,7 @@ func TestAddPicture(t *testing.T) {
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
string
{
"F21"
,
"A30"
,
"B30"
,
"Q1"
,
"Q8"
,
"Q15"
,
"Q22"
,
"Q28"
},
cells
)
// Test get picture cells with unsupported charset
f
.
Drawings
.
Delete
(
path
)
f
.
Pkg
.
Store
(
path
,
MacintoshCyrillicCharset
)
_
,
err
=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
...
...
@@ -226,6 +227,7 @@ func TestGetPicture(t *testing.T) {
// Test get pictures with unsupported charset
path
:=
"xl/drawings/drawing1.xml"
f
.
Drawings
.
Delete
(
path
)
f
.
Pkg
.
Store
(
path
,
MacintoshCyrillicCharset
)
_
,
err
=
f
.
getPicture
(
20
,
5
,
path
,
"xl/drawings/_rels/drawing2.xml.rels"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
...
...
@@ -388,7 +390,7 @@ func TestGetPictureCells(t *testing.T) {
func
TestExtractDecodeCellAnchor
(
t
*
testing
.
T
)
{
f
:=
NewFile
()
cond
:=
func
(
a
*
decode
CellAnchor
)
bool
{
return
true
}
cond
:=
func
(
a
*
decode
From
)
bool
{
return
true
}
cb
:=
func
(
a
*
decodeCellAnchor
,
r
*
xlsxRelationship
)
{}
f
.
extractDecodeCellAnchor
(
&
decodeCellAnchor
{
Content
:
string
(
MacintoshCyrillicCharset
)},
""
,
cond
,
cb
)
f
.
extractDecodeCellAnchor
(
&
xdrCellAnchor
{
GraphicFrame
:
string
(
MacintoshCyrillicCharset
)},
""
,
cond
,
cb
)
}
xmlDecodeDrawing.go
浏览文件 @
fe639faa
...
...
@@ -18,13 +18,32 @@ import "encoding/xml"
// specifies a two cell anchor placeholder for a group, a shape, or a drawing
// element. It moves with cells and its extents are in EMU units.
type
decodeCellAnchor
struct
{
EditAs
string
`xml:"editAs,attr,omitempty"`
From
*
decodeFrom
`xml:"from"`
To
*
decodeTo
`xml:"to"`
Sp
*
decodeSp
`xml:"sp"`
Pic
*
decodePic
`xml:"pic"`
ClientData
*
decodeClientData
`xml:"clientData"`
Content
string
`xml:",innerxml"`
EditAs
string
`xml:"editAs,attr,omitempty"`
From
*
decodeFrom
`xml:"from"`
To
*
decodeTo
`xml:"to"`
Sp
*
decodeSp
`xml:"sp"`
Pic
*
decodePic
`xml:"pic"`
ClientData
*
decodeClientData
`xml:"clientData"`
AlternateContent
[]
*
xlsxAlternateContent
`xml:"mc:AlternateContent"`
Content
string
`xml:",innerxml"`
}
// decodeCellAnchorPos defines the structure used to deserialize the cell anchor
// for adjust drawing object on inserting/deleting column/rows.
type
decodeCellAnchorPos
struct
{
EditAs
string
`xml:"editAs,attr,omitempty"`
From
*
xlsxFrom
`xml:"from"`
To
*
xlsxTo
`xml:"to"`
Pos
*
xlsxInnerXML
`xml:"pos"`
Ext
*
xlsxInnerXML
`xml:"ext"`
Sp
*
xlsxInnerXML
`xml:"sp"`
GrpSp
*
xlsxInnerXML
`xml:"grpSp"`
GraphicFrame
*
xlsxInnerXML
`xml:"graphicFrame"`
CxnSp
*
xlsxInnerXML
`xml:"cxnSp"`
Pic
*
xlsxInnerXML
`xml:"pic"`
ContentPart
*
xlsxInnerXML
`xml:"contentPart"`
AlternateContent
[]
*
xlsxAlternateContent
`xml:"AlternateContent"`
ClientData
*
xlsxInnerXML
`xml:"clientData"`
}
// xdrSp (Shape) directly maps the sp element. This element specifies the
...
...
xmlDrawing.go
浏览文件 @
fe639faa
...
...
@@ -230,6 +230,24 @@ type xdrCellAnchor struct {
ClientData
*
xdrClientData
`xml:"xdr:clientData"`
}
// xlsxCellAnchorPos defines the structure used to serialize the cell anchor for
// adjust drawing object on inserting/deleting column/rows.
type
xlsxCellAnchorPos
struct
{
EditAs
string
`xml:"editAs,attr,omitempty"`
From
*
xlsxFrom
`xml:"xdr:from"`
To
*
xlsxTo
`xml:"xdr:to"`
Pos
*
xlsxInnerXML
`xml:"xdr:pos"`
Ext
*
xlsxInnerXML
`xml:"xdr:ext"`
Sp
*
xlsxInnerXML
`xml:"xdr:sp"`
GrpSp
*
xlsxInnerXML
`xml:"xdr:grpSp"`
GraphicFrame
*
xlsxInnerXML
`xml:"xdr:graphicFrame"`
CxnSp
*
xlsxInnerXML
`xml:"xdr:cxnSp"`
Pic
*
xlsxInnerXML
`xml:"xdr:pic"`
ContentPart
*
xlsxInnerXML
`xml:"xdr:contentPart"`
AlternateContent
[]
*
xlsxAlternateContent
`xml:"mc:AlternateContent"`
ClientData
*
xlsxInnerXML
`xml:"xdr:clientData"`
}
// xlsxPoint2D describes the position of a drawing element within a spreadsheet.
type
xlsxPoint2D
struct
{
XMLName
xml
.
Name
`xml:"xdr:pos"`
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录