Skip to content

Commit

Permalink
This closes #1095, support to set and get document application proper…
Browse files Browse the repository at this point in the history
…ties
  • Loading branch information
xuri committed Dec 26, 2021
1 parent 089cd36 commit 6b1e592
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 52 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Excelize is a library written in pure Go providing a set of functions that allow
go get github.com/xuri/excelize
```

- If your packages are managed using [Go Modules](https://blog.golang.org/using-go-modules), please install with following command.
- If your packages are managed using [Go Modules](https://go.dev/blog/using-go-modules), please install with following command.

```bash
go get github.com/xuri/excelize/v2
Expand Down
2 changes: 1 addition & 1 deletion README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基
go get github.com/xuri/excelize
```

- 如果您使用 [Go Modules](https://blog.golang.org/using-go-modules) 管理软件包,请使用下面的命令来安装最新版本。
- 如果您使用 [Go Modules](https://go.dev/blog/using-go-modules) 管理软件包,请使用下面的命令来安装最新版本。

```bash
go get github.com/xuri/excelize/v2
Expand Down
1 change: 1 addition & 0 deletions calc.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ type formulaFuncs struct {
// WEIBULL
// WEIBULL.DIST
// XIRR
// XLOOKUP
// XNPV
// XOR
// YEAR
Expand Down
100 changes: 100 additions & 0 deletions docProps.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,106 @@ import (
"reflect"
)

// SetAppProps provides a function to set document application properties. The
// properties that can be set are:
//
// Property | Description
// -------------------+--------------------------------------------------------------------------
// Application | The name of the application that created this document.
// |
// ScaleCrop | Indicates the display mode of the document thumbnail. Set this element
// | to TRUE to enable scaling of the document thumbnail to the display. Set
// | this element to FALSE to enable cropping of the document thumbnail to
// | show only sections that will fit the display.
// |
// DocSecurity | Security level of a document as a numeric value. Document security is
// | defined as:
// | 1 - Document is password protected.
// | 2 - Document is recommended to be opened as read-only.
// | 3 - Document is enforced to be opened as read-only.
// | 4 - Document is locked for annotation.
// |
// Company | The name of a company associated with the document.
// |
// LinksUpToDate | Indicates whether hyperlinks in a document are up-to-date. Set this
// | element to TRUE to indicate that hyperlinks are updated. Set this
// | element to FALSE to indicate that hyperlinks are outdated.
// |
// HyperlinksChanged | Specifies that one or more hyperlinks in this part were updated
// | exclusively in this part by a producer. The next producer to open this
// | document shall update the hyperlink relationships with the new
// | hyperlinks specified in this part.
// |
// AppVersion | Specifies the version of the application which produced this document.
// | The content of this element shall be of the form XX.YYYY where X and Y
// | represent numerical values, or the document shall be considered
// | non-conformant.
//
// For example:
//
// err := f.SetAppProps(&excelize.AppProperties{
// Application: "Microsoft Excel",
// ScaleCrop: true,
// DocSecurity: 3,
// Company: "Company Name",
// LinksUpToDate: true,
// HyperlinksChanged: true,
// AppVersion: "16.0000",
// })
//
func (f *File) SetAppProps(appProperties *AppProperties) (err error) {
var (
app *xlsxProperties
fields []string
output []byte
immutable, mutable reflect.Value
field string
)
app = new(xlsxProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("docProps/app.xml")))).
Decode(app); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
}
fields = []string{"Application", "ScaleCrop", "DocSecurity", "Company", "LinksUpToDate", "HyperlinksChanged", "AppVersion"}
immutable, mutable = reflect.ValueOf(*appProperties), reflect.ValueOf(app).Elem()
for _, field = range fields {
immutableField := immutable.FieldByName(field)
switch immutableField.Kind() {
case reflect.Bool:
mutable.FieldByName(field).SetBool(immutableField.Bool())
case reflect.Int:
mutable.FieldByName(field).SetInt(immutableField.Int())
default:
mutable.FieldByName(field).SetString(immutableField.String())
}
}
app.Vt = NameSpaceDocumentPropertiesVariantTypes.Value
output, err = xml.Marshal(app)
f.saveFileList("docProps/app.xml", output)
return
}

// GetAppProps provides a function to get document application properties.
func (f *File) GetAppProps() (ret *AppProperties, err error) {
var app = new(xlsxProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("docProps/app.xml")))).
Decode(app); err != nil && err != io.EOF {
err = fmt.Errorf("xml decode error: %s", err)
return
}
ret, err = &AppProperties{
Application: app.Application,
ScaleCrop: app.ScaleCrop,
DocSecurity: app.DocSecurity,
Company: app.Company,
LinksUpToDate: app.LinksUpToDate,
HyperlinksChanged: app.HyperlinksChanged,
AppVersion: app.AppVersion,
}, nil
return
}

// SetDocProps provides a function to set document core properties. The
// properties that can be set are:
//
Expand Down
45 changes: 45 additions & 0 deletions docProps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,51 @@ import (

var MacintoshCyrillicCharset = []byte{0x8F, 0xF0, 0xE8, 0xE2, 0xE5, 0xF2, 0x20, 0xEC, 0xE8, 0xF0}

func TestSetAppProps(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
}
assert.NoError(t, f.SetAppProps(&AppProperties{
Application: "Microsoft Excel",
ScaleCrop: true,
DocSecurity: 3,
Company: "Company Name",
LinksUpToDate: true,
HyperlinksChanged: true,
AppVersion: "16.0000",
}))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetAppProps.xlsx")))
f.Pkg.Store("docProps/app.xml", nil)
assert.NoError(t, f.SetAppProps(&AppProperties{}))
assert.NoError(t, f.Close())

// Test unsupported charset
f = NewFile()
f.Pkg.Store("docProps/app.xml", MacintoshCyrillicCharset)
assert.EqualError(t, f.SetAppProps(&AppProperties{}), "xml decode error: XML syntax error on line 1: invalid UTF-8")
}

func TestGetAppProps(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
}
props, err := f.GetAppProps()
assert.NoError(t, err)
assert.Equal(t, props.Application, "Microsoft Macintosh Excel")
f.Pkg.Store("docProps/app.xml", nil)
_, err = f.GetAppProps()
assert.NoError(t, err)
assert.NoError(t, f.Close())

// Test unsupported charset
f = NewFile()
f.Pkg.Store("docProps/app.xml", MacintoshCyrillicCharset)
_, err = f.GetAppProps()
assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
}

func TestSetDocProps(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
if !assert.NoError(t, err) {
Expand Down
Binary file modified test/Book1.xlsx
Binary file not shown.
58 changes: 35 additions & 23 deletions xmlApp.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,50 @@ package excelize

import "encoding/xml"

// AppProperties directly maps the document application properties.
type AppProperties struct {
Application string
ScaleCrop bool
DocSecurity int
Company string
LinksUpToDate bool
HyperlinksChanged bool
AppVersion string
}

// xlsxProperties specifies to an OOXML document properties such as the
// template used, the number of pages and words, and the application name and
// version.
type xlsxProperties struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties Properties"`
Template string
Manager string
Company string
Pages int
Words int
Characters int
PresentationFormat string
Lines int
Paragraphs int
Slides int
Notes int
TotalTime int
HiddenSlides int
MMClips int
ScaleCrop bool
Vt string `xml:"xmlns:vt,attr"`
Template string `xml:",omitempty"`
Manager string `xml:",omitempty"`
Company string `xml:",omitempty"`
Pages int `xml:",omitempty"`
Words int `xml:",omitempty"`
Characters int `xml:",omitempty"`
PresentationFormat string `xml:",omitempty"`
Lines int `xml:",omitempty"`
Paragraphs int `xml:",omitempty"`
Slides int `xml:",omitempty"`
Notes int `xml:",omitempty"`
TotalTime int `xml:",omitempty"`
HiddenSlides int `xml:",omitempty"`
MMClips int `xml:",omitempty"`
ScaleCrop bool `xml:",omitempty"`
HeadingPairs *xlsxVectorVariant
TitlesOfParts *xlsxVectorLpstr
LinksUpToDate bool
CharactersWithSpaces int
SharedDoc bool
HyperlinkBase string
LinksUpToDate bool `xml:",omitempty"`
CharactersWithSpaces int `xml:",omitempty"`
SharedDoc bool `xml:",omitempty"`
HyperlinkBase string `xml:",omitempty"`
HLinks *xlsxVectorVariant
HyperlinksChanged bool
HyperlinksChanged bool `xml:",omitempty"`
DigSig *xlsxDigSig
Application string
AppVersion string
DocSecurity int
Application string `xml:",omitempty"`
AppVersion string `xml:",omitempty"`
DocSecurity int `xml:",omitempty"`
}

// xlsxVectorVariant specifies the set of hyperlinks that were in this
Expand Down
56 changes: 29 additions & 27 deletions xmlDrawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,39 @@ import (
// Source relationship and namespace list, associated prefixes and schema in which it was
// introduced.
var (
SourceRelationship = xml.Attr{Name: xml.Name{Local: "r", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
SourceRelationshipCompatibility = xml.Attr{Name: xml.Name{Local: "mc", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/markup-compatibility/2006"}
SourceRelationshipChart20070802 = xml.Attr{Name: xml.Name{Local: "c14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"}
SourceRelationshipChart2014 = xml.Attr{Name: xml.Name{Local: "c16", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2014/chart"}
SourceRelationshipChart201506 = xml.Attr{Name: xml.Name{Local: "c16r2", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2015/06/chart"}
NameSpaceSpreadSheet = xml.Attr{Name: xml.Name{Local: "xmlns"}, Value: "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
NameSpaceSpreadSheetX14 = xml.Attr{Name: xml.Name{Local: "x14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}
NameSpaceDrawingML = xml.Attr{Name: xml.Name{Local: "a", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/main"}
NameSpaceDrawingMLChart = xml.Attr{Name: xml.Name{Local: "c", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/chart"}
NameSpaceDrawingMLSpreadSheet = xml.Attr{Name: xml.Name{Local: "xdr", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"}
NameSpaceSpreadSheetX15 = xml.Attr{Name: xml.Name{Local: "x15", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"}
NameSpaceSpreadSheetExcel2006Main = xml.Attr{Name: xml.Name{Local: "xne", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/excel/2006/main"}
NameSpaceMacExcel2008Main = xml.Attr{Name: xml.Name{Local: "mx", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/mac/excel/2008/main"}
SourceRelationship = xml.Attr{Name: xml.Name{Local: "r", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}
SourceRelationshipCompatibility = xml.Attr{Name: xml.Name{Local: "mc", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/markup-compatibility/2006"}
SourceRelationshipChart20070802 = xml.Attr{Name: xml.Name{Local: "c14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"}
SourceRelationshipChart2014 = xml.Attr{Name: xml.Name{Local: "c16", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2014/chart"}
SourceRelationshipChart201506 = xml.Attr{Name: xml.Name{Local: "c16r2", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/drawing/2015/06/chart"}
NameSpaceSpreadSheet = xml.Attr{Name: xml.Name{Local: "xmlns"}, Value: "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}
NameSpaceSpreadSheetX14 = xml.Attr{Name: xml.Name{Local: "x14", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}
NameSpaceDrawingML = xml.Attr{Name: xml.Name{Local: "a", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/main"}
NameSpaceDrawingMLChart = xml.Attr{Name: xml.Name{Local: "c", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/chart"}
NameSpaceDrawingMLSpreadSheet = xml.Attr{Name: xml.Name{Local: "xdr", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"}
NameSpaceSpreadSheetX15 = xml.Attr{Name: xml.Name{Local: "x15", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"}
NameSpaceSpreadSheetExcel2006Main = xml.Attr{Name: xml.Name{Local: "xne", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/excel/2006/main"}
NameSpaceMacExcel2008Main = xml.Attr{Name: xml.Name{Local: "mx", Space: "xmlns"}, Value: "http://schemas.microsoft.com/office/mac/excel/2008/main"}
NameSpaceDocumentPropertiesVariantTypes = xml.Attr{Name: xml.Name{Local: "vt", Space: "xmlns"}, Value: "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"}
)

// Source relationship and namespace.
const (
SourceRelationshipOfficeDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
SourceRelationshipTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
SourceRelationshipDrawingML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
SourceRelationshipChartsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"
SourceRelationshipDialogsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet"
SourceRelationshipPivotTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable"
SourceRelationshipPivotCache = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition"
SourceRelationshipSharedStrings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"
SourceRelationshipOfficeDocument = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
SourceRelationshipTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
SourceRelationshipDrawingML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
SourceRelationshipChartsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"
SourceRelationshipDialogsheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet"
SourceRelationshipPivotTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable"
SourceRelationshipPivotCache = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition"
SourceRelationshipSharedStrings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"

SourceRelationshipVBAProject = "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
NameSpaceXML = "http://www.w3.org/XML/1998/namespace"
NameSpaceXMLSchemaInstance = "http://www.w3.org/2001/XMLSchema-instance"
Expand Down

0 comments on commit 6b1e592

Please sign in to comment.