123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- package xlsx
- import (
- "archive/zip"
- "encoding/xml"
- "fmt"
- "io"
- )
- const (
- // sheet state values as defined by
- // http://msdn.microsoft.com/en-us/library/office/documentformat.openxml.spreadsheet.sheetstatevalues.aspx
- sheetStateVisible = "visible"
- sheetStateHidden = "hidden"
- sheetStateVeryHidden = "veryHidden"
- )
- // xmlxWorkbookRels contains xmlxWorkbookRelations
- // which maps sheet id and sheet XML
- type xlsxWorkbookRels struct {
- XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/relationships Relationships"`
- Relationships []xlsxWorkbookRelation `xml:"Relationship"`
- }
- // xmlxWorkbookRelation maps sheet id and xl/worksheets/sheet%d.xml
- type xlsxWorkbookRelation struct {
- Id string `xml:",attr"`
- Target string `xml:",attr"`
- Type string `xml:",attr"`
- }
- // xlsxWorkbook directly maps the workbook element from the namespace
- // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
- // currently I have not checked it for completeness - it does as much
- // as I need.
- type xlsxWorkbook struct {
- XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main workbook"`
- FileVersion xlsxFileVersion `xml:"fileVersion"`
- WorkbookPr xlsxWorkbookPr `xml:"workbookPr"`
- WorkbookProtection xlsxWorkbookProtection `xml:"workbookProtection"`
- BookViews xlsxBookViews `xml:"bookViews"`
- Sheets xlsxSheets `xml:"sheets"`
- DefinedNames xlsxDefinedNames `xml:"definedNames"`
- CalcPr xlsxCalcPr `xml:"calcPr"`
- }
- // xlsxWorkbookProtection directly maps the workbookProtection element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- type xlsxWorkbookProtection struct {
- // We don't need this, yet.
- }
- // xlsxFileVersion directly maps the fileVersion element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- type xlsxFileVersion struct {
- AppName string `xml:"appName,attr,omitempty"`
- LastEdited string `xml:"lastEdited,attr,omitempty"`
- LowestEdited string `xml:"lowestEdited,attr,omitempty"`
- RupBuild string `xml:"rupBuild,attr,omitempty"`
- }
- // xlsxWorkbookPr directly maps the workbookPr element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- type xlsxWorkbookPr struct {
- DefaultThemeVersion string `xml:"defaultThemeVersion,attr,omitempty"`
- BackupFile bool `xml:"backupFile,attr,omitempty"`
- ShowObjects string `xml:"showObjects,attr,omitempty"`
- Date1904 bool `xml:"date1904,attr"`
- }
- // xlsxBookViews directly maps the bookViews element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- type xlsxBookViews struct {
- WorkBookView []xlsxWorkBookView `xml:"workbookView"`
- }
- // xlsxWorkBookView directly maps the workbookView element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- type xlsxWorkBookView struct {
- ActiveTab int `xml:"activeTab,attr,omitempty"`
- FirstSheet int `xml:"firstSheet,attr,omitempty"`
- ShowHorizontalScroll bool `xml:"showHorizontalScroll,attr,omitempty"`
- ShowVerticalScroll bool `xml:"showVerticalScroll,attr,omitempty"`
- ShowSheetTabs bool `xml:"showSheetTabs,attr,omitempty"`
- TabRatio int `xml:"tabRatio,attr,omitempty"`
- WindowHeight int `xml:"windowHeight,attr,omitempty"`
- WindowWidth int `xml:"windowWidth,attr,omitempty"`
- XWindow string `xml:"xWindow,attr,omitempty"`
- YWindow string `xml:"yWindow,attr,omitempty"`
- }
- // xlsxSheets directly maps the sheets element from the namespace
- // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
- // currently I have not checked it for completeness - it does as much
- // as I need.
- type xlsxSheets struct {
- Sheet []xlsxSheet `xml:"sheet"`
- }
- // xlsxSheet directly maps the sheet element from the namespace
- // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
- // currently I have not checked it for completeness - it does as much
- // as I need.
- type xlsxSheet struct {
- Name string `xml:"name,attr,omitempty"`
- SheetId string `xml:"sheetId,attr,omitempty"`
- Id string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
- State string `xml:"state,attr,omitempty"`
- }
- // xlsxDefinedNames directly maps the definedNames element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- type xlsxDefinedNames struct {
- DefinedName []xlsxDefinedName `xml:"definedName"`
- }
- // xlsxDefinedName directly maps the definedName element from the
- // namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
- // - currently I have not checked it for completeness - it does as
- // much as I need.
- // for a descriptions of the attributes see
- // https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.spreadsheet.definedname.aspx
- type xlsxDefinedName struct {
- Data string `xml:",chardata"`
- Name string `xml:"name,attr"`
- Comment string `xml:"comment,attr,omitempty"`
- CustomMenu string `xml:"customMenu,attr,omitempty"`
- Description string `xml:"description,attr,omitempty"`
- Help string `xml:"help,attr,omitempty"`
- ShortcutKey string `xml:"shortcutKey,attr,omitempty"`
- StatusBar string `xml:"statusBar,attr,omitempty"`
- LocalSheetID int `xml:"localSheetId,attr,omitempty"`
- FunctionGroupID int `xml:"functionGroupId,attr,omitempty"`
- Function bool `xml:"function,attr,omitempty"`
- Hidden bool `xml:"hidden,attr,omitempty"`
- VbProcedure bool `xml:"vbProcedure,attr,omitempty"`
- PublishToServer bool `xml:"publishToServer,attr,omitempty"`
- WorkbookParameter bool `xml:"workbookParameter,attr,omitempty"`
- Xlm bool `xml:"xml,attr,omitempty"`
- }
- // xlsxCalcPr directly maps the calcPr element from the namespace
- // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
- // currently I have not checked it for completeness - it does as much
- // as I need.
- type xlsxCalcPr struct {
- CalcId string `xml:"calcId,attr,omitempty"`
- IterateCount int `xml:"iterateCount,attr,omitempty"`
- RefMode string `xml:"refMode,attr,omitempty"`
- Iterate bool `xml:"iterate,attr,omitempty"`
- IterateDelta float64 `xml:"iterateDelta,attr,omitempty"`
- }
- // Helper function to lookup the file corresponding to a xlsxSheet object in the worksheets map
- func worksheetFileForSheet(sheet xlsxSheet, worksheets map[string]*zip.File, sheetXMLMap map[string]string) *zip.File {
- sheetName, ok := sheetXMLMap[sheet.Id]
- if !ok {
- if sheet.SheetId != "" {
- sheetName = fmt.Sprintf("sheet%s", sheet.SheetId)
- } else {
- sheetName = fmt.Sprintf("sheet%s", sheet.Id)
- }
- }
- return worksheets[sheetName]
- }
- // getWorksheetFromSheet() is an internal helper function to open a
- // sheetN.xml file, referred to by an xlsx.xlsxSheet struct, from the XLSX
- // file and unmarshal it an xlsx.xlsxWorksheet struct
- func getWorksheetFromSheet(sheet xlsxSheet, worksheets map[string]*zip.File, sheetXMLMap map[string]string, rowLimit int) (*xlsxWorksheet, error) {
- var r io.Reader
- var decoder *xml.Decoder
- var worksheet *xlsxWorksheet
- var err error
- worksheet = new(xlsxWorksheet)
- f := worksheetFileForSheet(sheet, worksheets, sheetXMLMap)
- if f == nil {
- return nil, fmt.Errorf("Unable to find sheet '%s'", sheet)
- }
- if rc, err := f.Open(); err != nil {
- return nil, err
- } else {
- defer rc.Close()
- r = rc
- }
- if rowLimit != NoRowLimit {
- r, err = truncateSheetXML(r, rowLimit)
- if err != nil {
- return nil, err
- }
- }
- decoder = xml.NewDecoder(r)
- err = decoder.Decode(worksheet)
- if err != nil {
- return nil, err
- }
- return worksheet, nil
- }
|