forked from p30928647/excelize
- 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
This commit is contained in:
parent
a08c8eb1ae
commit
b84bfa7eab
|
@ -179,14 +179,14 @@ func replaceWorkSheetsRelationshipsNameSpace(workbookMarshal string) string {
|
||||||
oldXmlns := `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`
|
oldXmlns := `<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`
|
||||||
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">`
|
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">`
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></sheetPr>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></tablePart>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></dimension>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></dimension>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></selection>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></selection>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></sheetFormatPr>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></sheetFormatPr>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></printOptions>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></printOptions>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></pageSetup>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></pageSetup>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></pageMargins>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></pageMargins>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></headerFooter>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></mergeCell>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></drawing>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></drawing>`, ` />`, -1)
|
||||||
return workbookMarshal
|
return workbookMarshal
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func TestExcelize(t *testing.T) {
|
||||||
f1.UpdateLinkedValue()
|
f1.UpdateLinkedValue()
|
||||||
f1.SetCellInt("SHEET2", "A1", 100)
|
f1.SetCellInt("SHEET2", "A1", 100)
|
||||||
f1.SetCellStr("SHEET2", "C11", "Knowns")
|
f1.SetCellStr("SHEET2", "C11", "Knowns")
|
||||||
f1.NewSheet(3, "TestSheet")
|
f1.NewSheet(3, "Maximum 31 characters allowed in sheet title.")
|
||||||
f1.SetCellInt("Sheet3", "A23", 10)
|
f1.SetCellInt("Sheet3", "A23", 10)
|
||||||
f1.SetCellStr("SHEET3", "b230", "10")
|
f1.SetCellStr("SHEET3", "b230", "10")
|
||||||
f1.SetCellStr("SHEET10", "b230", "10")
|
f1.SetCellStr("SHEET10", "b230", "10")
|
||||||
|
|
26
sheet.go
26
sheet.go
|
@ -19,9 +19,9 @@ func (f *File) NewSheet(index int, name string) {
|
||||||
// Create new sheet /xl/worksheets/sheet%d.xml
|
// Create new sheet /xl/worksheets/sheet%d.xml
|
||||||
f.setSheet(index)
|
f.setSheet(index)
|
||||||
// Update xl/_rels/workbook.xml.rels
|
// Update xl/_rels/workbook.xml.rels
|
||||||
f.addXlsxWorkbookRels(index)
|
rid := f.addXlsxWorkbookRels(index)
|
||||||
// Update xl/workbook.xml
|
// Update xl/workbook.xml
|
||||||
f.setWorkbook(index, name)
|
f.setWorkbook(name, rid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and update property of contents type of XLSX.
|
// Read and update property of contents type of XLSX.
|
||||||
|
@ -54,17 +54,17 @@ func (f *File) setSheet(index int) {
|
||||||
f.saveFileList(path, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
|
f.saveFileList(path, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update workbook property of XLSX.
|
// Update workbook property of XLSX. Maximum 31 characters allowed in sheet title.
|
||||||
func (f *File) setWorkbook(index int, name string) {
|
func (f *File) setWorkbook(name string, rid int) {
|
||||||
var content xlsxWorkbook
|
var content xlsxWorkbook
|
||||||
|
if len(name) > 31 {
|
||||||
|
name = name[0:31]
|
||||||
|
}
|
||||||
xml.Unmarshal([]byte(f.readXML(`xl/workbook.xml`)), &content)
|
xml.Unmarshal([]byte(f.readXML(`xl/workbook.xml`)), &content)
|
||||||
|
|
||||||
rels := f.readXlsxWorkbookRels()
|
|
||||||
rID := len(rels.Relationships)
|
|
||||||
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
|
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
|
||||||
Name: name,
|
Name: name,
|
||||||
SheetID: strconv.Itoa(index),
|
SheetID: strconv.Itoa(rid),
|
||||||
ID: "rId" + strconv.Itoa(rID),
|
ID: `rId` + strconv.Itoa(rid),
|
||||||
})
|
})
|
||||||
output, err := xml.Marshal(content)
|
output, err := xml.Marshal(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -81,7 +81,7 @@ func (f *File) readXlsxWorkbookRels() xlsxWorkbookRels {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update workbook relationships property of XLSX.
|
// Update workbook relationships property of XLSX.
|
||||||
func (f *File) addXlsxWorkbookRels(sheet int) {
|
func (f *File) addXlsxWorkbookRels(sheet int) int {
|
||||||
content := f.readXlsxWorkbookRels()
|
content := f.readXlsxWorkbookRels()
|
||||||
rID := len(content.Relationships) + 1
|
rID := len(content.Relationships) + 1
|
||||||
ID := bytes.Buffer{}
|
ID := bytes.Buffer{}
|
||||||
|
@ -101,6 +101,7 @@ func (f *File) addXlsxWorkbookRels(sheet int) {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
f.saveFileList(`xl/_rels/workbook.xml.rels`, string(output))
|
f.saveFileList(`xl/_rels/workbook.xml.rels`, string(output))
|
||||||
|
return rID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update docProps/app.xml file of XML.
|
// Update docProps/app.xml file of XML.
|
||||||
|
@ -128,6 +129,7 @@ func replaceRelationshipsID(workbookMarshal string) string {
|
||||||
rids = strings.Replace(rids, `<tableParts count="0"></tableParts>`, ``, -1)
|
rids = strings.Replace(rids, `<tableParts count="0"></tableParts>`, ``, -1)
|
||||||
rids = strings.Replace(rids, `<picture></picture>`, ``, -1)
|
rids = strings.Replace(rids, `<picture></picture>`, ``, -1)
|
||||||
rids = strings.Replace(rids, `<legacyDrawing></legacyDrawing>`, ``, -1)
|
rids = strings.Replace(rids, `<legacyDrawing></legacyDrawing>`, ``, -1)
|
||||||
|
rids = strings.Replace(rids, `<tabColor></tabColor>`, ``, -1)
|
||||||
return strings.Replace(rids, `<drawing rid="`, `<drawing r:id="`, -1)
|
return strings.Replace(rids, `<drawing rid="`, `<drawing r:id="`, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,10 +193,12 @@ func workBookCompatibility(workbookMarshal string) string {
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></workbookView>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></workbookView>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></fileVersion>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></fileVersion>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></workbookPr>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></workbookPr>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></definedNames>`, ` />`, -1)
|
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></calcPr>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></calcPr>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></workbookProtection>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></workbookProtection>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></fileRecoveryPr>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></fileRecoveryPr>`, ` />`, -1)
|
||||||
workbookMarshal = strings.Replace(workbookMarshal, `></hyperlink>`, ` />`, -1)
|
workbookMarshal = strings.Replace(workbookMarshal, `></hyperlink>`, ` />`, -1)
|
||||||
|
workbookMarshal = strings.Replace(workbookMarshal, `></tabColor>`, ` />`, -1)
|
||||||
|
workbookMarshal = strings.Replace(workbookMarshal, `></pageSetUpPr>`, ` />`, -1)
|
||||||
|
workbookMarshal = strings.Replace(workbookMarshal, `></pane>`, ` />`, -1)
|
||||||
return workbookMarshal
|
return workbookMarshal
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ type xlsxWorkbookPr struct {
|
||||||
DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
|
DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
|
||||||
BackupFile bool `xml:"backupFile,attr,omitempty"`
|
BackupFile bool `xml:"backupFile,attr,omitempty"`
|
||||||
ShowObjects string `xml:"showObjects,attr,omitempty"`
|
ShowObjects string `xml:"showObjects,attr,omitempty"`
|
||||||
Date1904 bool `xml:"date1904,attr"`
|
Date1904 bool `xml:"date1904,attr,omitempty"`
|
||||||
|
CodeName string `xml:"codeName,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxBookViews directly maps the bookViews element from the
|
// xlsxBookViews directly maps the bookViews element from the
|
||||||
|
|
|
@ -132,25 +132,34 @@ type xlsxSheetViews struct {
|
||||||
// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
|
// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
|
||||||
// currently I have not checked it for completeness - it does as much
|
// currently I have not checked it for completeness - it does as much
|
||||||
// as I need.
|
// as I need.
|
||||||
|
//
|
||||||
|
// A single sheet view definition. When more than one sheet view is
|
||||||
|
// defined in the file, it means that when opening the workbook, each
|
||||||
|
// sheet view corresponds to a separate window within the spreadsheet
|
||||||
|
// application, where each window is showing the particular sheet
|
||||||
|
// containing the same workbookViewId value, the last sheetView
|
||||||
|
// definition is loaded, and the others are discarded. When multiple
|
||||||
|
// windows are viewing the same sheet, multiple sheetView elements
|
||||||
|
// (with corresponding workbookView entries) are saved.
|
||||||
type xlsxSheetView struct {
|
type xlsxSheetView struct {
|
||||||
// WindowProtection bool `xml:"windowProtection,attr"`
|
WindowProtection bool `xml:"windowProtection,attr,omitempty"`
|
||||||
// ShowFormulas bool `xml:"showFormulas,attr"`
|
ShowFormulas bool `xml:"showFormulas,attr,omitempty"`
|
||||||
ShowGridLines string `xml:"showGridLines,attr,omitempty"`
|
ShowGridLines string `xml:"showGridLines,attr,omitempty"`
|
||||||
// ShowRowColHeaders bool `xml:"showRowColHeaders,attr"`
|
ShowRowColHeaders bool `xml:"showRowColHeaders,attr,omitempty"`
|
||||||
// ShowZeros bool `xml:"showZeros,attr"`
|
ShowZeros bool `xml:"showZeros,attr,omitempty"`
|
||||||
// RightToLeft bool `xml:"rightToLeft,attr"`
|
RightToLeft bool `xml:"rightToLeft,attr,omitempty"`
|
||||||
TabSelected bool `xml:"tabSelected,attr"`
|
TabSelected bool `xml:"tabSelected,attr,omitempty"`
|
||||||
// ShowOutlineSymbols bool `xml:"showOutlineSymbols,attr"`
|
ShowOutlineSymbols bool `xml:"showOutlineSymbols,attr,omitempty"`
|
||||||
// DefaultGridColor bool `xml:"defaultGridColor,attr"`
|
DefaultGridColor bool `xml:"defaultGridColor,attr"`
|
||||||
// View string `xml:"view,attr"`
|
View string `xml:"view,attr,omitempty"`
|
||||||
TopLeftCell string `xml:"topLeftCell,attr,omitempty"`
|
TopLeftCell string `xml:"topLeftCell,attr,omitempty"`
|
||||||
// ColorId int `xml:"colorId,attr"`
|
ColorId int `xml:"colorId,attr,omitempty"`
|
||||||
ZoomScale float64 `xml:"zoomScale,attr,omitempty"`
|
ZoomScale float64 `xml:"zoomScale,attr,omitempty"`
|
||||||
ZoomScaleNormal float64 `xml:"zoomScaleNormal,attr,omitempty"`
|
ZoomScaleNormal float64 `xml:"zoomScaleNormal,attr,omitempty"`
|
||||||
ZoomScalePageLayoutView float64 `xml:"zoomScalePageLayoutView,attr,omitempty"`
|
ZoomScalePageLayoutView float64 `xml:"zoomScalePageLayoutView,attr,omitempty"`
|
||||||
WorkbookViewID int `xml:"workbookViewId,attr"`
|
WorkbookViewID int `xml:"workbookViewId,attr"`
|
||||||
Selection []xlsxSelection `xml:"selection"`
|
|
||||||
Pane *xlsxPane `xml:"pane,omitempty"`
|
Pane *xlsxPane `xml:"pane,omitempty"`
|
||||||
|
Selection []xlsxSelection `xml:"selection"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxSelection directly maps the selection element in the namespace
|
// xlsxSelection directly maps the selection element in the namespace
|
||||||
|
@ -161,7 +170,7 @@ type xlsxSelection struct {
|
||||||
Pane string `xml:"pane,attr,omitempty"`
|
Pane string `xml:"pane,attr,omitempty"`
|
||||||
ActiveCell string `xml:"activeCell,attr,omitempty"`
|
ActiveCell string `xml:"activeCell,attr,omitempty"`
|
||||||
ActiveCellID int `xml:"activeCellId,attr"`
|
ActiveCellID int `xml:"activeCellId,attr"`
|
||||||
SQRef string `xml:"sqref,attr"`
|
SQRef string `xml:"sqref,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxSelection directly maps the selection element in the namespace
|
// xlsxSelection directly maps the selection element in the namespace
|
||||||
|
@ -181,8 +190,12 @@ type xlsxPane struct {
|
||||||
// currently I have not checked it for completeness - it does as much
|
// currently I have not checked it for completeness - it does as much
|
||||||
// as I need.
|
// as I need.
|
||||||
type xlsxSheetPr struct {
|
type xlsxSheetPr struct {
|
||||||
FilterMode bool `xml:"filterMode,attr"`
|
XMLName xml.Name `xml:"sheetPr"`
|
||||||
PageSetUpPr []xlsxPageSetUpPr `xml:"pageSetUpPr"`
|
FilterMode bool `xml:"filterMode,attr,omitempty"`
|
||||||
|
CodeName string `xml:"codeName,attr,omitempty"`
|
||||||
|
EnableFormatConditionsCalculation int `xml:"enableFormatConditionsCalculation,attr,omitempty"`
|
||||||
|
TabColor xlsxTabColor `xml:"tabColor,omitempty"`
|
||||||
|
PageSetUpPr xlsxPageSetUpPr `xml:"pageSetUpPr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxPageSetUpPr directly maps the pageSetupPr element in the namespace
|
// xlsxPageSetUpPr directly maps the pageSetupPr element in the namespace
|
||||||
|
@ -190,7 +203,15 @@ type xlsxSheetPr struct {
|
||||||
// currently I have not checked it for completeness - it does as much
|
// currently I have not checked it for completeness - it does as much
|
||||||
// as I need.
|
// as I need.
|
||||||
type xlsxPageSetUpPr struct {
|
type xlsxPageSetUpPr struct {
|
||||||
FitToPage bool `xml:"fitToPage,attr"`
|
FitToPage bool `xml:"fitToPage,attr"` // Flag indicating whether the Fit to Page print option is enabled.
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxTabColor directly maps the tabColor element in the namespace
|
||||||
|
// currently I have not checked it for completeness - it does as much
|
||||||
|
// as I need.
|
||||||
|
type xlsxTabColor struct {
|
||||||
|
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.
|
||||||
|
Tint uint8 `xml:"tint,attr,omitempty"` // Specifies the tint value applied to the color.
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxCols directly maps the cols element in the namespace
|
// xlsxCols directly maps the cols element in the namespace
|
||||||
|
@ -278,7 +299,7 @@ type xlsxF struct {
|
||||||
Content string `xml:",chardata"`
|
Content string `xml:",chardata"`
|
||||||
T string `xml:"t,attr,omitempty"` // Formula type
|
T string `xml:"t,attr,omitempty"` // Formula type
|
||||||
Ref string `xml:"ref,attr,omitempty"` // Shared formula ref
|
Ref string `xml:"ref,attr,omitempty"` // Shared formula ref
|
||||||
Si int `xml:"si,attr,omitempty"` // Shared formula index
|
Si string `xml:"si,attr,omitempty"` // Shared formula index
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxHyperlinks directly maps the hyperlinks element in the namespace
|
// xlsxHyperlinks directly maps the hyperlinks element in the namespace
|
||||||
|
|
Loading…
Reference in New Issue