Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xuri
excelize
提交
838232fd
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 搜索 >>
未验证
提交
838232fd
编写于
3月 26, 2024
作者:
M
Matthew Sackman
提交者:
GitHub
3月 26, 2024
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for get the Microsoft 365 cell images (#1857)
- Update unit tests
上级
703b7377
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
259 addition
and
22 deletion
+259
-22
excelize.go
excelize.go
+38
-0
picture.go
picture.go
+66
-7
picture_test.go
picture_test.go
+56
-2
templates.go
templates.go
+16
-13
xmlMetaData.go
xmlMetaData.go
+83
-0
未找到文件。
excelize.go
浏览文件 @
838232fd
...
...
@@ -589,3 +589,41 @@ func (f *File) setContentTypePartProjectExtensions(contentType string) error {
}
return
err
}
// metadataReader provides a function to get the pointer to the structure
// after deserialization of xl/metadata.xml.
func
(
f
*
File
)
metadataReader
()
(
*
xlsxMetadata
,
error
)
{
var
mataData
xlsxMetadata
if
err
:=
f
.
xmlNewDecoder
(
bytes
.
NewReader
(
namespaceStrictToTransitional
(
f
.
readXML
(
defaultXMLMetadata
))))
.
Decode
(
&
mataData
);
err
!=
nil
&&
err
!=
io
.
EOF
{
return
&
mataData
,
err
}
return
&
mataData
,
nil
}
// richValueRelReader provides a function to get the pointer to the structure
// after deserialization of xl/richData/richValueRel.xml.
func
(
f
*
File
)
richValueRelReader
()
(
*
xlsxRichValueRels
,
error
)
{
var
richValueRels
xlsxRichValueRels
if
err
:=
f
.
xmlNewDecoder
(
bytes
.
NewReader
(
namespaceStrictToTransitional
(
f
.
readXML
(
defaultXMLRichDataRichValueRel
))))
.
Decode
(
&
richValueRels
);
err
!=
nil
&&
err
!=
io
.
EOF
{
return
&
richValueRels
,
err
}
return
&
richValueRels
,
nil
}
// getRichDataRichValueRelRelationships provides a function to get drawing
// relationships from xl/richData/_rels/richValueRel.xml.rels by given
// relationship ID.
func
(
f
*
File
)
getRichDataRichValueRelRelationships
(
rID
string
)
*
xlsxRelationship
{
if
rels
,
_
:=
f
.
relsReader
(
defaultXMLRichDataRichValueRelRels
);
rels
!=
nil
{
rels
.
mu
.
Lock
()
defer
rels
.
mu
.
Unlock
()
for
_
,
v
:=
range
rels
.
Relationships
{
if
v
.
ID
==
rID
{
return
&
v
}
}
}
return
nil
}
picture.go
浏览文件 @
838232fd
...
...
@@ -497,13 +497,13 @@ func (f *File) GetPictureCells(sheet string) ([]string, error) {
}
f
.
mu
.
Unlock
()
if
ws
.
Drawing
==
nil
{
return
f
.
get
Embedded
ImageCells
(
sheet
)
return
f
.
getImageCells
(
sheet
)
}
target
:=
f
.
getSheetRelationshipsTargetByID
(
sheet
,
ws
.
Drawing
.
RID
)
drawingXML
:=
strings
.
TrimPrefix
(
strings
.
ReplaceAll
(
target
,
".."
,
"xl"
),
"/"
)
drawingRelationships
:=
strings
.
ReplaceAll
(
strings
.
ReplaceAll
(
target
,
"../drawings"
,
"xl/drawings/_rels"
),
".xml"
,
".xml.rels"
)
embeddedImageCells
,
err
:=
f
.
get
Embedded
ImageCells
(
sheet
)
embeddedImageCells
,
err
:=
f
.
getImageCells
(
sheet
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -771,9 +771,9 @@ func (f *File) cellImagesReader() (*decodeCellImages, error) {
return
f
.
DecodeCellImages
,
nil
}
// get
EmbeddedImageCells returns all the Kingsoft WPS Office embedded image
// cells reference by given worksheet name.
func
(
f
*
File
)
get
Embedded
ImageCells
(
sheet
string
)
([]
string
,
error
)
{
// get
ImageCells returns all the Microsoft 365 cell images and the Kingsoft WPS
//
Office embedded image
cells reference by given worksheet name.
func
(
f
*
File
)
getImageCells
(
sheet
string
)
([]
string
,
error
)
{
var
(
err
error
cells
[]
string
...
...
@@ -791,14 +791,73 @@ func (f *File) getEmbeddedImageCells(sheet string) ([]string, error) {
}
cells
=
append
(
cells
,
c
.
R
)
}
r
,
err
:=
f
.
getImageCellRel
(
&
c
)
if
err
!=
nil
{
return
cells
,
err
}
if
r
!=
nil
{
cells
=
append
(
cells
,
c
.
R
)
}
}
}
return
cells
,
err
}
// getCellImages provides a function to get the Kingsoft WPS Office embedded
// cell images by given worksheet name and cell reference.
// getImageCellRel returns the Microsoft 365 cell image relationship.
func
(
f
*
File
)
getImageCellRel
(
c
*
xlsxC
)
(
*
xlsxRelationship
,
error
)
{
var
r
*
xlsxRelationship
if
c
.
Vm
==
nil
||
c
.
V
!=
formulaErrorVALUE
{
return
r
,
nil
}
metaData
,
err
:=
f
.
metadataReader
()
if
err
!=
nil
{
return
r
,
err
}
vmd
:=
metaData
.
ValueMetadata
if
vmd
==
nil
||
int
(
*
c
.
Vm
)
>
len
(
vmd
.
Bk
)
||
len
(
vmd
.
Bk
[
*
c
.
Vm
-
1
]
.
Rc
)
==
0
{
return
r
,
err
}
richValueRel
,
err
:=
f
.
richValueRelReader
()
if
err
!=
nil
{
return
r
,
err
}
if
vmd
.
Bk
[
*
c
.
Vm
-
1
]
.
Rc
[
0
]
.
V
>=
len
(
richValueRel
.
Rels
)
{
return
r
,
err
}
rID
:=
richValueRel
.
Rels
[
vmd
.
Bk
[
*
c
.
Vm
-
1
]
.
Rc
[
0
]
.
V
]
.
ID
if
r
=
f
.
getRichDataRichValueRelRelationships
(
rID
);
r
!=
nil
&&
r
.
Type
!=
SourceRelationshipImage
{
return
nil
,
err
}
return
r
,
err
}
// getCellImages provides a function to get the Microsoft 365 cell images and
// the Kingsoft WPS Office embedded cell images by given worksheet name and cell
// reference.
func
(
f
*
File
)
getCellImages
(
sheet
,
cell
string
)
([]
Picture
,
error
)
{
pics
,
err
:=
f
.
getDispImages
(
sheet
,
cell
)
if
err
!=
nil
{
return
pics
,
err
}
_
,
err
=
f
.
getCellStringFunc
(
sheet
,
cell
,
func
(
x
*
xlsxWorksheet
,
c
*
xlsxC
)
(
string
,
bool
,
error
)
{
r
,
err
:=
f
.
getImageCellRel
(
c
)
if
err
!=
nil
||
r
==
nil
{
return
""
,
true
,
err
}
pic
:=
Picture
{
Extension
:
filepath
.
Ext
(
r
.
Target
),
Format
:
&
GraphicOptions
{}}
if
buffer
,
_
:=
f
.
Pkg
.
Load
(
strings
.
TrimPrefix
(
strings
.
ReplaceAll
(
r
.
Target
,
".."
,
"xl"
),
"/"
));
buffer
!=
nil
{
pic
.
File
=
buffer
.
([]
byte
)
pics
=
append
(
pics
,
pic
)
}
return
""
,
true
,
nil
})
return
pics
,
err
}
// getDispImages provides a function to get the Kingsoft WPS Office embedded
// cell images by given worksheet name and cell reference.
func
(
f
*
File
)
getDispImages
(
sheet
,
cell
string
)
([]
Picture
,
error
)
{
formula
,
err
:=
f
.
GetCellFormula
(
sheet
,
cell
)
if
err
!=
nil
{
return
nil
,
err
...
...
picture_test.go
浏览文件 @
838232fd
...
...
@@ -448,13 +448,67 @@ func TestGetCellImages(t *testing.T) {
_
,
err
:=
f
.
getCellImages
(
"Sheet1"
,
"A1"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
assert
.
NoError
(
t
,
f
.
Close
())
// Test get the Microsoft 365 cell images
f
=
NewFile
()
assert
.
NoError
(
t
,
f
.
AddPicture
(
"Sheet1"
,
"A1"
,
filepath
.
Join
(
"test"
,
"images"
,
"excel.png"
),
nil
))
f
.
Pkg
.
Store
(
defaultXMLMetadata
,
[]
byte
(
`<metadata><valueMetadata count="1"><bk><rc t="1" v="0"/></bk></valueMetadata></metadata>`
))
f
.
Pkg
.
Store
(
defaultXMLRichDataRichValueRel
,
[]
byte
(
`<richValueRels><rel r:id="rId1"/></richValueRels>`
))
f
.
Pkg
.
Store
(
defaultXMLRichDataRichValueRelRels
,
[]
byte
(
fmt
.
Sprintf
(
`<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="%s" Target="../media/image1.png"/></Relationships>`
,
SourceRelationshipImage
)))
f
.
Sheet
.
Store
(
"xl/worksheets/sheet1.xml"
,
&
xlsxWorksheet
{
SheetData
:
xlsxSheetData
{
Row
:
[]
xlsxRow
{
{
R
:
1
,
C
:
[]
xlsxC
{{
R
:
"A1"
,
T
:
"e"
,
V
:
formulaErrorVALUE
,
Vm
:
uintPtr
(
1
)}}},
}},
})
pics
,
err
:=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
1
,
len
(
pics
))
cells
,
err
:=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Equal
(
t
,
[]
string
{
"A1"
},
cells
)
// Test get the Microsoft 365 cell images without image relationships parts
f
.
Relationships
.
Delete
(
defaultXMLRichDataRichValueRelRels
)
f
.
Pkg
.
Store
(
defaultXMLRichDataRichValueRelRels
,
[]
byte
(
fmt
.
Sprintf
(
`<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="%s" Target="../media/image1.png"/></Relationships>`
,
SourceRelationshipHyperLink
)))
pics
,
err
=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Empty
(
t
,
pics
)
// Test get the Microsoft 365 cell images with unsupported charset rich data rich value relationships
f
.
Relationships
.
Delete
(
defaultXMLRichDataRichValueRelRels
)
f
.
Pkg
.
Store
(
defaultXMLRichDataRichValueRelRels
,
MacintoshCyrillicCharset
)
pics
,
err
=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Empty
(
t
,
pics
)
// Test get the Microsoft 365 cell images with unsupported charset rich data rich value
f
.
Pkg
.
Store
(
defaultXMLRichDataRichValueRel
,
MacintoshCyrillicCharset
)
_
,
err
=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
// Test get the Microsoft 365 image cells without block of metadata records
cells
,
err
=
f
.
GetPictureCells
(
"Sheet1"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
assert
.
Empty
(
t
,
cells
)
// Test get the Microsoft 365 cell images with rich data rich value relationships
f
.
Pkg
.
Store
(
defaultXMLMetadata
,
[]
byte
(
`<metadata><valueMetadata count="1"><bk><rc t="1" v="0"/></bk></valueMetadata></metadata>`
))
f
.
Pkg
.
Store
(
defaultXMLRichDataRichValueRel
,
[]
byte
(
`<richValueRels/>`
))
pics
,
err
=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Empty
(
t
,
pics
)
// Test get the Microsoft 365 cell images with unsupported charset meta data
f
.
Pkg
.
Store
(
defaultXMLMetadata
,
MacintoshCyrillicCharset
)
_
,
err
=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
// Test get the Microsoft 365 cell images without block of metadata records
f
.
Pkg
.
Store
(
defaultXMLMetadata
,
[]
byte
(
`<metadata><valueMetadata/></metadata>`
))
pics
,
err
=
f
.
GetPictures
(
"Sheet1"
,
"A1"
)
assert
.
NoError
(
t
,
err
)
assert
.
Empty
(
t
,
pics
)
}
func
TestGet
Embedded
ImageCells
(
t
*
testing
.
T
)
{
func
TestGetImageCells
(
t
*
testing
.
T
)
{
f
:=
NewFile
()
f
.
Sheet
.
Delete
(
"xl/worksheets/sheet1.xml"
)
f
.
Pkg
.
Store
(
"xl/worksheets/sheet1.xml"
,
MacintoshCyrillicCharset
)
_
,
err
:=
f
.
get
Embedded
ImageCells
(
"Sheet1"
)
_
,
err
:=
f
.
getImageCells
(
"Sheet1"
)
assert
.
EqualError
(
t
,
err
,
"XML syntax error on line 1: invalid UTF-8"
)
assert
.
NoError
(
t
,
f
.
Close
())
}
templates.go
浏览文件 @
838232fd
...
...
@@ -266,19 +266,22 @@ var supportedChartDataLabelsPosition = map[ChartType][]ChartDataLabelPositionTyp
}
const
(
defaultTempFileSST
=
"sharedStrings"
defaultXMLPathCalcChain
=
"xl/calcChain.xml"
defaultXMLPathCellImages
=
"xl/cellimages.xml"
defaultXMLPathCellImagesRels
=
"xl/_rels/cellimages.xml.rels"
defaultXMLPathContentTypes
=
"[Content_Types].xml"
defaultXMLPathDocPropsApp
=
"docProps/app.xml"
defaultXMLPathDocPropsCore
=
"docProps/core.xml"
defaultXMLPathSharedStrings
=
"xl/sharedStrings.xml"
defaultXMLPathStyles
=
"xl/styles.xml"
defaultXMLPathTheme
=
"xl/theme/theme1.xml"
defaultXMLPathVolatileDeps
=
"xl/volatileDependencies.xml"
defaultXMLPathWorkbook
=
"xl/workbook.xml"
defaultXMLPathWorkbookRels
=
"xl/_rels/workbook.xml.rels"
defaultTempFileSST
=
"sharedStrings"
defaultXMLMetadata
=
"xl/metadata.xml"
defaultXMLPathCalcChain
=
"xl/calcChain.xml"
defaultXMLPathCellImages
=
"xl/cellimages.xml"
defaultXMLPathCellImagesRels
=
"xl/_rels/cellimages.xml.rels"
defaultXMLPathContentTypes
=
"[Content_Types].xml"
defaultXMLPathDocPropsApp
=
"docProps/app.xml"
defaultXMLPathDocPropsCore
=
"docProps/core.xml"
defaultXMLPathSharedStrings
=
"xl/sharedStrings.xml"
defaultXMLPathStyles
=
"xl/styles.xml"
defaultXMLPathTheme
=
"xl/theme/theme1.xml"
defaultXMLPathVolatileDeps
=
"xl/volatileDependencies.xml"
defaultXMLPathWorkbook
=
"xl/workbook.xml"
defaultXMLPathWorkbookRels
=
"xl/_rels/workbook.xml.rels"
defaultXMLRichDataRichValueRel
=
"xl/richData/richValueRel.xml"
defaultXMLRichDataRichValueRelRels
=
"xl/richData/_rels/richValueRel.xml.rels"
)
// IndexedColorMapping is the table of default mappings from indexed color value
...
...
xmlMetaData.go
0 → 100644
浏览文件 @
838232fd
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to and
// read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
// Supports complex components by high compatibility, and provided streaming
// API for generating or reading data from a worksheet with huge amounts of
// data. This library needs Go version 1.18 or later.
package
excelize
import
"encoding/xml"
// xlsxMetadata directly maps the metadata element. A cell in a spreadsheet
// application can have metadata associated with it. Metadata is just a set of
// additional properties about the particular cell, and this metadata is stored
// in the metadata xml part. There are two types of metadata: cell metadata and
// value metadata. Cell metadata contains information about the cell itself,
// and this metadata can be carried along with the cell as it moves
// (insert, shift, copy/paste, merge, unmerge, etc). Value metadata is
// information about the value of a particular cell. Value metadata properties
// can be propagated along with the value as it is referenced in formulas.
type
xlsxMetadata
struct
{
XMLName
xml
.
Name
`xml:"metadata"`
MetadataTypes
*
xlsxInnerXML
`xml:"metadataTypes"`
MetadataStrings
*
xlsxInnerXML
`xml:"metadataStrings"`
MdxMetadata
*
xlsxInnerXML
`xml:"mdxMetadata"`
FutureMetadata
[]
xlsxFutureMetadata
`xml:"futureMetadata"`
CellMetadata
*
xlsxMetadataBlocks
`xml:"cellMetadata"`
ValueMetadata
*
xlsxMetadataBlocks
`xml:"valueMetadata"`
ExtLst
*
xlsxInnerXML
`xml:"extLst"`
}
// xlsxFutureMetadata directly maps the futureMetadata element. This element
// represents future metadata information.
type
xlsxFutureMetadata
struct
{
Bk
[]
xlsxFutureMetadataBlock
`xml:"bk"`
ExtLst
*
xlsxInnerXML
`xml:"extLst"`
}
// xlsxFutureMetadataBlock directly maps the kb element. This element represents
// a block of future metadata information. This is a location for storing
// feature extension information.
type
xlsxFutureMetadataBlock
struct
{
ExtLst
*
xlsxInnerXML
`xml:"extLst"`
}
// xlsxMetadataBlocks directly maps the metadata element. This element
// represents cell metadata information. Cell metadata is information metadata
// about a specific cell, and it stays tied to that cell position.
type
xlsxMetadataBlocks
struct
{
Count
int
`xml:"count,attr,omitempty"`
Bk
[]
xlsxMetadataBlock
`xml:"bk"`
}
// xlsxMetadataBlock directly maps the bk element. This element represents a
// block of metadata records.
type
xlsxMetadataBlock
struct
{
Rc
[]
xlsxMetadataRecord
`xml:"rc"`
}
// xlsxMetadataRecord directly maps the rc element. This element represents a
// reference to a specific metadata record.
type
xlsxMetadataRecord
struct
{
T
int
`xml:"t,attr"`
V
int
`xml:"v,attr"`
}
// xlsxRichValueRels directly maps the richValueRels element. This element that
// specifies a list of rich value relationships.
type
xlsxRichValueRels
struct
{
XMLName
xml
.
Name
`xml:"richValueRels"`
Rels
[]
xlsxRichValueRelRelationship
`xml:"rel"`
ExtLst
*
xlsxInnerXML
`xml:"extLst"`
}
// xlsxRichValueRelRelationship directly maps the rel element. This element
// specifies a relationship for a rich value property.
type
xlsxRichValueRelRelationship
struct
{
ID
string
`xml:"id,attr"`
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录