Skip to content

Commit b84bfa7

Browse files
committed
- Update maximum 31 characters allowed in sheet title;
- Fix issue XML tag `headerFooter` and `sheetPr` element self-close errors cause file corruption; - Fix issue `Section` and `Pane` element order make file corruption in some case; - Change sheet `rId` calculation method in `/xl/workbook.xml`, fix makes file corruption in some case; - Compatibility improved: add `xlsxTabColor` struct and some XML element for worksheet
1 parent a08c8eb commit b84bfa7

File tree

5 files changed

+59
-33
lines changed

5 files changed

+59
-33
lines changed

excelize.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ func replaceWorkSheetsRelationshipsNameSpace(workbookMarshal string) string {
179179
oldXmlns := `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`
180180
newXmlns := `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">`
181181
workbookMarshal = strings.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
182-
workbookMarshal = strings.Replace(workbookMarshal, `></sheetPr>`, ` />`, -1)
182+
workbookMarshal = strings.Replace(workbookMarshal, `></tablePart>`, ` />`, -1)
183183
workbookMarshal = strings.Replace(workbookMarshal, `></dimension>`, ` />`, -1)
184184
workbookMarshal = strings.Replace(workbookMarshal, `></selection>`, ` />`, -1)
185185
workbookMarshal = strings.Replace(workbookMarshal, `></sheetFormatPr>`, ` />`, -1)
186186
workbookMarshal = strings.Replace(workbookMarshal, `></printOptions>`, ` />`, -1)
187187
workbookMarshal = strings.Replace(workbookMarshal, `></pageSetup>`, ` />`, -1)
188188
workbookMarshal = strings.Replace(workbookMarshal, `></pageMargins>`, ` />`, -1)
189-
workbookMarshal = strings.Replace(workbookMarshal, `></headerFooter>`, ` />`, -1)
189+
workbookMarshal = strings.Replace(workbookMarshal, `></mergeCell>`, ` />`, -1)
190190
workbookMarshal = strings.Replace(workbookMarshal, `></drawing>`, ` />`, -1)
191191
return workbookMarshal
192192
}

excelize_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestExcelize(t *testing.T) {
2424
f1.UpdateLinkedValue()
2525
f1.SetCellInt("SHEET2", "A1", 100)
2626
f1.SetCellStr("SHEET2", "C11", "Knowns")
27-
f1.NewSheet(3, "TestSheet")
27+
f1.NewSheet(3, "Maximum 31 characters allowed in sheet title.")
2828
f1.SetCellInt("Sheet3", "A23", 10)
2929
f1.SetCellStr("SHEET3", "b230", "10")
3030
f1.SetCellStr("SHEET10", "b230", "10")

sheet.go

+15-11
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ func (f *File) NewSheet(index int, name string) {
1919
// Create new sheet /xl/worksheets/sheet%d.xml
2020
f.setSheet(index)
2121
// Update xl/_rels/workbook.xml.rels
22-
f.addXlsxWorkbookRels(index)
22+
rid := f.addXlsxWorkbookRels(index)
2323
// Update xl/workbook.xml
24-
f.setWorkbook(index, name)
24+
f.setWorkbook(name, rid)
2525
}
2626

2727
// Read and update property of contents type of XLSX.
@@ -54,17 +54,17 @@ func (f *File) setSheet(index int) {
5454
f.saveFileList(path, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
5555
}
5656

57-
// Update workbook property of XLSX.
58-
func (f *File) setWorkbook(index int, name string) {
57+
// Update workbook property of XLSX. Maximum 31 characters allowed in sheet title.
58+
func (f *File) setWorkbook(name string, rid int) {
5959
var content xlsxWorkbook
60+
if len(name) > 31 {
61+
name = name[0:31]
62+
}
6063
xml.Unmarshal([]byte(f.readXML(`xl/workbook.xml`)), &content)
61-
62-
rels := f.readXlsxWorkbookRels()
63-
rID := len(rels.Relationships)
6464
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
6565
Name: name,
66-
SheetID: strconv.Itoa(index),
67-
ID: "rId" + strconv.Itoa(rID),
66+
SheetID: strconv.Itoa(rid),
67+
ID: `rId` + strconv.Itoa(rid),
6868
})
6969
output, err := xml.Marshal(content)
7070
if err != nil {
@@ -81,7 +81,7 @@ func (f *File) readXlsxWorkbookRels() xlsxWorkbookRels {
8181
}
8282

8383
// Update workbook relationships property of XLSX.
84-
func (f *File) addXlsxWorkbookRels(sheet int) {
84+
func (f *File) addXlsxWorkbookRels(sheet int) int {
8585
content := f.readXlsxWorkbookRels()
8686
rID := len(content.Relationships) + 1
8787
ID := bytes.Buffer{}
@@ -101,6 +101,7 @@ func (f *File) addXlsxWorkbookRels(sheet int) {
101101
fmt.Println(err)
102102
}
103103
f.saveFileList(`xl/_rels/workbook.xml.rels`, string(output))
104+
return rID
104105
}
105106

106107
// Update docProps/app.xml file of XML.
@@ -128,6 +129,7 @@ func replaceRelationshipsID(workbookMarshal string) string {
128129
rids = strings.Replace(rids, `<tableParts count="0"></tableParts>`, ``, -1)
129130
rids = strings.Replace(rids, `<picture></picture>`, ``, -1)
130131
rids = strings.Replace(rids, `<legacyDrawing></legacyDrawing>`, ``, -1)
132+
rids = strings.Replace(rids, `<tabColor></tabColor>`, ``, -1)
131133
return strings.Replace(rids, `<drawing rid="`, `<drawing r:id="`, -1)
132134
}
133135

@@ -191,10 +193,12 @@ func workBookCompatibility(workbookMarshal string) string {
191193
workbookMarshal = strings.Replace(workbookMarshal, `></workbookView>`, ` />`, -1)
192194
workbookMarshal = strings.Replace(workbookMarshal, `></fileVersion>`, ` />`, -1)
193195
workbookMarshal = strings.Replace(workbookMarshal, `></workbookPr>`, ` />`, -1)
194-
workbookMarshal = strings.Replace(workbookMarshal, `></definedNames>`, ` />`, -1)
195196
workbookMarshal = strings.Replace(workbookMarshal, `></calcPr>`, ` />`, -1)
196197
workbookMarshal = strings.Replace(workbookMarshal, `></workbookProtection>`, ` />`, -1)
197198
workbookMarshal = strings.Replace(workbookMarshal, `></fileRecoveryPr>`, ` />`, -1)
198199
workbookMarshal = strings.Replace(workbookMarshal, `></hyperlink>`, ` />`, -1)
200+
workbookMarshal = strings.Replace(workbookMarshal, `></tabColor>`, ` />`, -1)
201+
workbookMarshal = strings.Replace(workbookMarshal, `></pageSetUpPr>`, ` />`, -1)
202+
workbookMarshal = strings.Replace(workbookMarshal, `></pane>`, ` />`, -1)
199203
return workbookMarshal
200204
}

xmlWorkbook.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ type xlsxWorkbookPr struct {
7474
DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
7575
BackupFile bool `xml:"backupFile,attr,omitempty"`
7676
ShowObjects string `xml:"showObjects,attr,omitempty"`
77-
Date1904 bool `xml:"date1904,attr"`
77+
Date1904 bool `xml:"date1904,attr,omitempty"`
78+
CodeName string `xml:"codeName,attr,omitempty"`
7879
}
7980

8081
// xlsxBookViews directly maps the bookViews element from the

xmlWorksheet.go

+39-18
Original file line numberDiff line numberDiff line change
@@ -132,25 +132,34 @@ type xlsxSheetViews struct {
132132
// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
133133
// currently I have not checked it for completeness - it does as much
134134
// as I need.
135+
//
136+
// A single sheet view definition. When more than one sheet view is
137+
// defined in the file, it means that when opening the workbook, each
138+
// sheet view corresponds to a separate window within the spreadsheet
139+
// application, where each window is showing the particular sheet
140+
// containing the same workbookViewId value, the last sheetView
141+
// definition is loaded, and the others are discarded. When multiple
142+
// windows are viewing the same sheet, multiple sheetView elements
143+
// (with corresponding workbookView entries) are saved.
135144
type xlsxSheetView struct {
136-
// WindowProtection bool `xml:"windowProtection,attr"`
137-
// ShowFormulas bool `xml:"showFormulas,attr"`
138-
ShowGridLines string `xml:"showGridLines,attr,omitempty"`
139-
// ShowRowColHeaders bool `xml:"showRowColHeaders,attr"`
140-
// ShowZeros bool `xml:"showZeros,attr"`
141-
// RightToLeft bool `xml:"rightToLeft,attr"`
142-
TabSelected bool `xml:"tabSelected,attr"`
143-
// ShowOutlineSymbols bool `xml:"showOutlineSymbols,attr"`
144-
// DefaultGridColor bool `xml:"defaultGridColor,attr"`
145-
// View string `xml:"view,attr"`
146-
TopLeftCell string `xml:"topLeftCell,attr,omitempty"`
147-
// ColorId int `xml:"colorId,attr"`
145+
WindowProtection bool `xml:"windowProtection,attr,omitempty"`
146+
ShowFormulas bool `xml:"showFormulas,attr,omitempty"`
147+
ShowGridLines string `xml:"showGridLines,attr,omitempty"`
148+
ShowRowColHeaders bool `xml:"showRowColHeaders,attr,omitempty"`
149+
ShowZeros bool `xml:"showZeros,attr,omitempty"`
150+
RightToLeft bool `xml:"rightToLeft,attr,omitempty"`
151+
TabSelected bool `xml:"tabSelected,attr,omitempty"`
152+
ShowOutlineSymbols bool `xml:"showOutlineSymbols,attr,omitempty"`
153+
DefaultGridColor bool `xml:"defaultGridColor,attr"`
154+
View string `xml:"view,attr,omitempty"`
155+
TopLeftCell string `xml:"topLeftCell,attr,omitempty"`
156+
ColorId int `xml:"colorId,attr,omitempty"`
148157
ZoomScale float64 `xml:"zoomScale,attr,omitempty"`
149158
ZoomScaleNormal float64 `xml:"zoomScaleNormal,attr,omitempty"`
150159
ZoomScalePageLayoutView float64 `xml:"zoomScalePageLayoutView,attr,omitempty"`
151160
WorkbookViewID int `xml:"workbookViewId,attr"`
152-
Selection []xlsxSelection `xml:"selection"`
153161
Pane *xlsxPane `xml:"pane,omitempty"`
162+
Selection []xlsxSelection `xml:"selection"`
154163
}
155164

156165
// xlsxSelection directly maps the selection element in the namespace
@@ -161,7 +170,7 @@ type xlsxSelection struct {
161170
Pane string `xml:"pane,attr,omitempty"`
162171
ActiveCell string `xml:"activeCell,attr,omitempty"`
163172
ActiveCellID int `xml:"activeCellId,attr"`
164-
SQRef string `xml:"sqref,attr"`
173+
SQRef string `xml:"sqref,attr,omitempty"`
165174
}
166175

167176
// xlsxSelection directly maps the selection element in the namespace
@@ -181,16 +190,28 @@ type xlsxPane struct {
181190
// currently I have not checked it for completeness - it does as much
182191
// as I need.
183192
type xlsxSheetPr struct {
184-
FilterMode bool `xml:"filterMode,attr"`
185-
PageSetUpPr []xlsxPageSetUpPr `xml:"pageSetUpPr"`
193+
XMLName xml.Name `xml:"sheetPr"`
194+
FilterMode bool `xml:"filterMode,attr,omitempty"`
195+
CodeName string `xml:"codeName,attr,omitempty"`
196+
EnableFormatConditionsCalculation int `xml:"enableFormatConditionsCalculation,attr,omitempty"`
197+
TabColor xlsxTabColor `xml:"tabColor,omitempty"`
198+
PageSetUpPr xlsxPageSetUpPr `xml:"pageSetUpPr"`
186199
}
187200

188201
// xlsxPageSetUpPr directly maps the pageSetupPr element in the namespace
189202
// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
190203
// currently I have not checked it for completeness - it does as much
191204
// as I need.
192205
type xlsxPageSetUpPr struct {
193-
FitToPage bool `xml:"fitToPage,attr"`
206+
FitToPage bool `xml:"fitToPage,attr"` // Flag indicating whether the Fit to Page print option is enabled.
207+
}
208+
209+
// xlsxTabColor directly maps the tabColor element in the namespace
210+
// currently I have not checked it for completeness - it does as much
211+
// as I need.
212+
type xlsxTabColor struct {
213+
Theme int `xml:"theme,attr,omitempty"` // (Theme Color) A zero-based index into the <clrScheme> collection (§20.1.6.2), referencing a particular <sysClr> or <srgbClr> value expressed in the Theme part.
214+
Tint uint8 `xml:"tint,attr,omitempty"` // Specifies the tint value applied to the color.
194215
}
195216

196217
// xlsxCols directly maps the cols element in the namespace
@@ -278,7 +299,7 @@ type xlsxF struct {
278299
Content string `xml:",chardata"`
279300
T string `xml:"t,attr,omitempty"` // Formula type
280301
Ref string `xml:"ref,attr,omitempty"` // Shared formula ref
281-
Si int `xml:"si,attr,omitempty"` // Shared formula index
302+
Si string `xml:"si,attr,omitempty"` // Shared formula index
282303
}
283304

284305
// xlsxHyperlinks directly maps the hyperlinks element in the namespace

0 commit comments

Comments
 (0)