forked from p30928647/excelize
- Fix issue: sheet protection and conditional formatting proprietary missing after save;
- Update workbook and sheet relationships and self-close tag replacement hack functions
This commit is contained in:
parent
c5cc500b88
commit
f958f05a3b
|
@ -183,15 +183,6 @@ func replaceWorkSheetsRelationshipsNameSpace(workbookMarshal string) string {
|
|||
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">`
|
||||
workbookMarshal = strings.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></tablePart>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></dimension>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></selection>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></sheetFormatPr>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></printOptions>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></pageSetup>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></pageMargins>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></mergeCell>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></drawing>`, ` />`, -1)
|
||||
return workbookMarshal
|
||||
}
|
||||
|
||||
|
|
7
lib.go
7
lib.go
|
@ -7,7 +7,6 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ReadZip takes a pointer to a zip.ReadCloser and returns a
|
||||
|
@ -28,7 +27,7 @@ func ReadZipReader(r *zip.Reader) (map[string]string, int, error) {
|
|||
if len(v.Name) > 18 {
|
||||
if v.Name[0:19] == `xl/worksheets/sheet` {
|
||||
var xlsx xlsxWorksheet
|
||||
xml.Unmarshal([]byte(strings.Replace(fileList[v.Name], `<drawing r:id=`, `<drawing rid=`, -1)), &xlsx)
|
||||
xml.Unmarshal([]byte(fileList[v.Name]), &xlsx)
|
||||
xlsx = checkRow(xlsx)
|
||||
output, _ := xml.Marshal(xlsx)
|
||||
fileList[v.Name] = replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output)))
|
||||
|
@ -39,10 +38,10 @@ func ReadZipReader(r *zip.Reader) (map[string]string, int, error) {
|
|||
return fileList, worksheets, nil
|
||||
}
|
||||
|
||||
// Read XML content as string and replace drawing property in XML namespace of sheet.
|
||||
// Read XML content as string.
|
||||
func (f *File) readXML(name string) string {
|
||||
if content, ok := f.XLSX[name]; ok {
|
||||
return strings.Replace(content, `<drawing r:id=`, `<drawing rid=`, -1)
|
||||
return content
|
||||
}
|
||||
return ``
|
||||
}
|
||||
|
|
96
sheet.go
96
sheet.go
|
@ -8,6 +8,55 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Define the empty element and self-close XML tags hack rules for
|
||||
// xl/workbook.xml and xl/worksheets/sheet%d.xml.
|
||||
var (
|
||||
WorkbookRules = []map[string]string{
|
||||
{`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="`: `r:id="`},
|
||||
{`></sheet>`: ` />`},
|
||||
{`></workbookView>`: ` />`},
|
||||
{`></fileVersion>`: ` />`},
|
||||
{`></workbookPr>`: ` />`},
|
||||
{`></calcPr>`: ` />`},
|
||||
{`></workbookProtection>`: ` />`},
|
||||
{`></fileRecoveryPr>`: ` />`},
|
||||
{`></hyperlink>`: ` />`},
|
||||
{`></tabColor>`: ` />`},
|
||||
{`></pageSetUpPr>`: ` />`},
|
||||
{`></pane>`: ` />`},
|
||||
{`<extLst></extLst>`: ``},
|
||||
{`<fileRecoveryPr />`: ``},
|
||||
{`<workbookProtection />`: ``},
|
||||
{`<pivotCaches></pivotCaches>`: ``},
|
||||
{`<externalReferences></externalReferences>`: ``},
|
||||
{`<workbookProtection></workbookProtection>`: ``},
|
||||
{`<definedNames></definedNames>`: ``},
|
||||
{`<fileRecoveryPr></fileRecoveryPr>`: ``},
|
||||
{`<workbookPr />`: ``},
|
||||
}
|
||||
SheetRules = []map[string]string{
|
||||
{`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="`: `r:id="`},
|
||||
{`<drawing></drawing>`: ``},
|
||||
{`<drawing />`: ``},
|
||||
{`<hyperlinks></hyperlinks>`: ``},
|
||||
{`<tableParts count="0"></tableParts>`: ``},
|
||||
{`<picture></picture>`: ``},
|
||||
{`<legacyDrawing></legacyDrawing>`: ``},
|
||||
{`<tabColor></tabColor>`: ``},
|
||||
{`<sheetProtection></sheetProtection>`: ``},
|
||||
{`<conditionalFormatting></conditionalFormatting>`: ``},
|
||||
{`<extLst></extLst>`: ``},
|
||||
{`></tablePart>`: ` />`},
|
||||
{`></dimension>`: ` />`},
|
||||
{`></selection>`: ` />`},
|
||||
{`></sheetFormatPr>`: ` />`},
|
||||
{`></printOptions>`: ` />`},
|
||||
{`></pageSetup>`: ` />`},
|
||||
{`></pageMargins>`: ` />`},
|
||||
{`></mergeCell>`: ` />`},
|
||||
}
|
||||
)
|
||||
|
||||
// NewSheet provice function to greate a new sheet by given index, when
|
||||
// creating a new XLSX file, the default sheet will be create, when you
|
||||
// create a new file, you need to ensure that the index is continuous.
|
||||
|
@ -122,17 +171,6 @@ func replaceRelationshipsNameSpace(workbookMarshal string) string {
|
|||
return strings.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
|
||||
}
|
||||
|
||||
// replace relationships ID in worksheets/sheet%d.xml
|
||||
func replaceRelationshipsID(workbookMarshal string) string {
|
||||
rids := strings.Replace(workbookMarshal, `<drawing rid="" />`, ``, -1)
|
||||
rids = strings.Replace(rids, `<hyperlinks></hyperlinks>`, ``, -1)
|
||||
rids = strings.Replace(rids, `<tableParts count="0"></tableParts>`, ``, -1)
|
||||
rids = strings.Replace(rids, `<picture></picture>`, ``, -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)
|
||||
}
|
||||
|
||||
// SetActiveSheet provide function to set default active sheet of XLSX by given index.
|
||||
func (f *File) SetActiveSheet(index int) {
|
||||
var content xlsxWorkbook
|
||||
|
@ -188,26 +226,20 @@ func (f *File) SetActiveSheet(index int) {
|
|||
|
||||
// Replace xl/workbook.xml XML tags to self-closing for compatible Office Excel 2007.
|
||||
func workBookCompatibility(workbookMarshal string) string {
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="`, `r:id="`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></sheet>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></workbookView>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></fileVersion>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></workbookPr>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></calcPr>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></workbookProtection>`, ` />`, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `></fileRecoveryPr>`, ` />`, -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)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<extLst></extLst>`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<fileRecoveryPr />`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<workbookProtection />`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<pivotCaches></pivotCaches>`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<externalReferences></externalReferences>`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<workbookProtection></workbookProtection>`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<definedNames></definedNames>`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<fileRecoveryPr></fileRecoveryPr>`, ``, -1)
|
||||
workbookMarshal = strings.Replace(workbookMarshal, `<workbookPr />`, ``, -1)
|
||||
for _, rules := range WorkbookRules {
|
||||
for k, v := range rules {
|
||||
workbookMarshal = strings.Replace(workbookMarshal, k, v, -1)
|
||||
}
|
||||
}
|
||||
return workbookMarshal
|
||||
}
|
||||
|
||||
// replace relationships ID in worksheets/sheet%d.xml
|
||||
func replaceRelationshipsID(workbookMarshal string) string {
|
||||
for _, rules := range SheetRules {
|
||||
for k, v := range rules {
|
||||
workbookMarshal = strings.Replace(workbookMarshal, k, v, -1)
|
||||
}
|
||||
}
|
||||
return workbookMarshal
|
||||
}
|
||||
|
|
|
@ -9,29 +9,31 @@ import "encoding/xml"
|
|||
// currently I have not checked it for completeness - it does as much
|
||||
// as I need.
|
||||
type xlsxWorksheet struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main worksheet"`
|
||||
SheetPr xlsxSheetPr `xml:"sheetPr"`
|
||||
Dimension xlsxDimension `xml:"dimension"`
|
||||
SheetViews xlsxSheetViews `xml:"sheetViews"`
|
||||
SheetFormatPr xlsxSheetFormatPr `xml:"sheetFormatPr"`
|
||||
Cols *xlsxCols `xml:"cols,omitempty"`
|
||||
SheetData xlsxSheetData `xml:"sheetData"`
|
||||
Hyperlinks xlsxHyperlinks `xml:"hyperlinks"`
|
||||
MergeCells *xlsxMergeCells `xml:"mergeCells,omitempty"`
|
||||
PrintOptions xlsxPrintOptions `xml:"printOptions"`
|
||||
PageMargins xlsxPageMargins `xml:"pageMargins"`
|
||||
PageSetUp xlsxPageSetUp `xml:"pageSetup"`
|
||||
HeaderFooter xlsxHeaderFooter `xml:"headerFooter"`
|
||||
Drawing xlsxDrawing `xml:"drawing"`
|
||||
LegacyDrawing xlsxLegacyDrawing `xml:"legacyDrawing"`
|
||||
Picture xlsxPicture `xml:"picture"`
|
||||
TableParts xlsxTableParts `xml:"tableParts"`
|
||||
ExtLst xlsxExtLst `xml:"extLst"`
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main worksheet"`
|
||||
SheetPr xlsxSheetPr `xml:"sheetPr"`
|
||||
Dimension xlsxDimension `xml:"dimension"`
|
||||
SheetViews xlsxSheetViews `xml:"sheetViews"`
|
||||
SheetFormatPr xlsxSheetFormatPr `xml:"sheetFormatPr"`
|
||||
Cols *xlsxCols `xml:"cols,omitempty"`
|
||||
SheetData xlsxSheetData `xml:"sheetData"`
|
||||
SheetProtection xlsxSheetProtection `xml:"sheetProtection"`
|
||||
MergeCells *xlsxMergeCells `xml:"mergeCells,omitempty"`
|
||||
ConditionalFormatting xlsxConditionalFormatting `xml:"conditionalFormatting"`
|
||||
Hyperlinks xlsxHyperlinks `xml:"hyperlinks"`
|
||||
PrintOptions xlsxPrintOptions `xml:"printOptions"`
|
||||
PageMargins xlsxPageMargins `xml:"pageMargins"`
|
||||
PageSetUp xlsxPageSetUp `xml:"pageSetup"`
|
||||
HeaderFooter xlsxHeaderFooter `xml:"headerFooter"`
|
||||
Drawing xlsxDrawing `xml:"drawing"`
|
||||
LegacyDrawing xlsxLegacyDrawing `xml:"legacyDrawing"`
|
||||
Picture xlsxPicture `xml:"picture"`
|
||||
TableParts xlsxTableParts `xml:"tableParts"`
|
||||
ExtLst xlsxExtLst `xml:"extLst"`
|
||||
}
|
||||
|
||||
// xlsxDrawing change r:id to rid in the namespace.
|
||||
type xlsxDrawing struct {
|
||||
RID string `xml:"rid,attr"`
|
||||
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
|
||||
}
|
||||
|
||||
// xlsxHeaderFooter directly maps the headerFooter element in the namespace
|
||||
|
@ -303,6 +305,39 @@ type xlsxF struct {
|
|||
Si string `xml:"si,attr,omitempty"` // Shared formula index
|
||||
}
|
||||
|
||||
// xlsxSheetProtection collection expresses the sheet protection options
|
||||
// to enforce when the sheet is protected.
|
||||
type xlsxSheetProtection struct {
|
||||
AlgorithmName string `xml:"algorithmName,attr,omitempty"`
|
||||
AutoFilter int `xml:"autoFilter,attr,omitempty"`
|
||||
DeleteColumns int `xml:"deleteColumns,attr,omitempty"`
|
||||
DeleteRows int `xml:"deleteRows,attr,omitempty"`
|
||||
FormatCells int `xml:"formatCells,attr,omitempty"`
|
||||
FormatColumns int `xml:"formatColumns,attr,omitempty"`
|
||||
FormatRows int `xml:"formatRows,attr,omitempty"`
|
||||
HashValue string `xml:"hashValue,attr,omitempty"`
|
||||
InsertColumns int `xml:"insertColumns,attr,omitempty"`
|
||||
InsertHyperlinks int `xml:"insertHyperlinks,attr,omitempty"`
|
||||
InsertRows int `xml:"insertRows,attr,omitempty"`
|
||||
Objects int `xml:"objects,attr,omitempty"`
|
||||
PivotTables int `xml:"pivotTables,attr,omitempty"`
|
||||
SaltValue string `xml:"saltValue,attr,omitempty"`
|
||||
Scenarios int `xml:"scenarios,attr,omitempty"`
|
||||
SelectLockedCells int `xml:"selectLockedCells,attr,omitempty"`
|
||||
SelectUnlockedCell int `xml:"selectUnlockedCell,attr,omitempty"`
|
||||
Sheet int `xml:"sheet,attr,omitempty"`
|
||||
Sort int `xml:"sort,attr,omitempty"`
|
||||
SpinCount int `xml:"spinCount,attr,omitempty"`
|
||||
}
|
||||
|
||||
// A Conditional Format is a format, such as cell shading or font color,
|
||||
// that a spreadsheet application can automatically apply to cells if a
|
||||
// specified condition is true. This collection expresses conditional
|
||||
// formatting rules applied to a particular cell or range.
|
||||
type xlsxConditionalFormatting struct {
|
||||
CfRule string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxHyperlinks directly maps the hyperlinks element in the namespace
|
||||
// http://schemas.openxmlformats.org/spreadsheetml/2006/main
|
||||
type xlsxHyperlinks struct {
|
||||
|
|
Loading…
Reference in New Issue