开源摘星计划(WeOpen Star) 是由腾源会 2022 年推出的全新项目,旨在为开源人提供成长激励,为开源项目提供成长支持,助力开发者更好地了解开源,更快地跨越鸿沟,参与到开源的具体贡献与实践中。
不管你是开源萌新,还是希望更深度参与开源贡献的老兵,跟随“开源摘星计划”开启你的开源之旅,从一篇学习笔记、到一段代码的提交,不断挖掘自己的潜能,最终成长为开源社区的“闪亮之星”。
我们将同你一起,探索更多的可能性!
项目地址: WeOpen-Star:https://github.com/weopenprojects/WeOpen-Star
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本。
func (f *File) SetDocProps(docProperties *DocProperties) error
设置工作簿的核心属性。可以设置的属性包括:
属性 | 描述 |
---|---|
Category | 文档内容的分类 |
ContentStatus | 文档内容的状态。例如: 值可能包括 “Draft”、“Reviewed” 和 “Final” |
Created | 文档创建时间 |
Creator | 创作者 |
Description | 资源内容的说明 |
Identifier | 对给定上下文中的资源的明确引用 |
Keywords | 文档关键词 |
Language | 文档内容的主要语言 |
LastModifiedBy | 执行上次修改的用户 |
Modified | 文档修改时间 |
Revision | 文档修订版本 |
Subject | 文档主题 |
Title | 文档标题 |
Version | 版本号,该值由用户或应用程序设置 |
下面举一个使用例子:
err := f.SetDocProps(&excelize.DocProperties{
Category: "category",
ContentStatus: "Draft",
Created: "2019-06-04T22:00:10Z",
Creator: "Go Excelize",
Description: "This file created by Go Excelize",
Identifier: "xlsx",
Keywords: "Spreadsheet",
LastModifiedBy: "Go Author",
Modified: "2019-06-04T22:00:10Z",
Revision: "0",
Subject: "Test Subject",
Title: "Test Title",
Language: "en-US",
Version: "1.0.0",
})
然后直接上源码:
func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
var (
core *decodeCoreProperties
newProps *xlsxCoreProperties
fields []string
output []byte
immutable, mutable reflect.Value
field, val string
)
core = new(decodeCoreProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
}
newProps, err = &xlsxCoreProperties{
Dc: NameSpaceDublinCore,
Dcterms: NameSpaceDublinCoreTerms,
Dcmitype: NameSpaceDublinCoreMetadataInitiative,
XSI: NameSpaceXMLSchemaInstance,
Title: core.Title,
Subject: core.Subject,
Creator: core.Creator,
Keywords: core.Keywords,
Description: core.Description,
LastModifiedBy: core.LastModifiedBy,
Language: core.Language,
Identifier: core.Identifier,
Revision: core.Revision,
ContentStatus: core.ContentStatus,
Category: core.Category,
Version: core.Version,
}, nil
if core.Created != nil {
newProps.Created = &xlsxDcTerms{Type: core.Created.Type, Text: core.Created.Text}
}
if core.Modified != nil {
newProps.Modified = &xlsxDcTerms{Type: core.Modified.Type, Text: core.Modified.Text}
}
fields = []string{
"Category", "ContentStatus", "Creator", "Description", "Identifier", "Keywords",
"LastModifiedBy", "Revision", "Subject", "Title", "Language", "Version",
}
immutable, mutable = reflect.ValueOf(*docProperties), reflect.ValueOf(newProps).Elem()
for _, field = range fields {
if val = immutable.FieldByName(field).String(); val != "" {
mutable.FieldByName(field).SetString(val)
}
}
if docProperties.Created != "" {
newProps.Created = &xlsxDcTerms{Type: "dcterms:W3CDTF", Text: docProperties.Created}
}
if docProperties.Modified != "" {
newProps.Modified = &xlsxDcTerms{Type: "dcterms:W3CDTF", Text: docProperties.Modified}
}
output, err = xml.Marshal(newProps)
f.saveFileList(defaultXMLPathDocPropsCore, output)
return
}
这个API的实现看起来很复杂,我们来对他进行拆解:
core = new(decodeCoreProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
}
这部分的作用是对defaultXMLPathDocPropsCore文件进行读取,即docProps/core.xml文件:
defaultXMLPathDocPropsCore = "docProps/core.xml"
然后对xml文件进行解码。
newProps, err = &xlsxCoreProperties{
Dc: NameSpaceDublinCore,
Dcterms: NameSpaceDublinCoreTerms,
Dcmitype: NameSpaceDublinCoreMetadataInitiative,
XSI: NameSpaceXMLSchemaInstance,
Title: core.Title,
Subject: core.Subject,
Creator: core.Creator,
Keywords: core.Keywords,
Description: core.Description,
LastModifiedBy: core.LastModifiedBy,
Language: core.Language,
Identifier: core.Identifier,
Revision: core.Revision,
ContentStatus: core.ContentStatus,
Category: core.Category,
Version: core.Version,
}, nil
if core.Created != nil {
newProps.Created = &xlsxDcTerms{Type: core.Created.Type, Text: core.Created.Text}
}
if core.Modified != nil {
newProps.Modified = &xlsxDcTerms{Type: core.Modified.Type, Text: core.Modified.Text}
}
fields = []string{
"Category", "ContentStatus", "Creator", "Description", "Identifier", "Keywords",
"LastModifiedBy", "Revision", "Subject", "Title", "Language", "Version",
}
immutable, mutable = reflect.ValueOf(*docProperties), reflect.ValueOf(newProps).Elem()
for _, field = range fields {
if val = immutable.FieldByName(field).String(); val != "" {
mutable.FieldByName(field).SetString(val)
}
}
if docProperties.Created != "" {
newProps.Created = &xlsxDcTerms{Type: "dcterms:W3CDTF", Text: docProperties.Created}
}
if docProperties.Modified != "" {
newProps.Modified = &xlsxDcTerms{Type: "dcterms:W3CDTF", Text: docProperties.Modified}
}
output, err = xml.Marshal(newProps)
f.saveFileList(defaultXMLPathDocPropsCore, output)
将获取的信息创建一个新的xlsxCoreProperties结构体。然后将结构体序列化之后保存为配置文件即可。
下面介绍工作簿的最后一个API:GetDocProps()
// GetDocProps provides a function to get document core properties.
func (f *File) GetDocProps() (ret *DocProperties, err error) {
core := new(decodeCoreProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
}
ret, err = &DocProperties{
Category: core.Category,
ContentStatus: core.ContentStatus,
Creator: core.Creator,
Description: core.Description,
Identifier: core.Identifier,
Keywords: core.Keywords,
LastModifiedBy: core.LastModifiedBy,
Revision: core.Revision,
Subject: core.Subject,
Title: core.Title,
Language: core.Language,
Version: core.Version,
}, nil
if core.Created != nil {
ret.Created = core.Created.Text
}
if core.Modified != nil {
ret.Modified = core.Modified.Text
}
return
}
逻辑很简单,读取并解码xml文件,将获得的结果core中的变量放入ret,其也是一个DocProperties结构体,最后返回即可。