package workbook import ( "archive/zip" "fmt" "os" "time" ) // Workbook 表示一个Excel工作簿 type Workbook struct { Worksheets []*Worksheet Properties *WorkbookProperties Relationships *Relationships Styles *Styles Theme *Theme ContentTypes *ContentTypes Rels *WorkbookRels SharedStrings *SharedStrings } // WorkbookProperties 包含工作簿的元数据 type WorkbookProperties struct { Title string Subject string Creator string Keywords string Description string LastModifiedBy string Revision int Created time.Time Modified time.Time } // NewWorkbook 创建一个新的Excel工作簿 func NewWorkbook() *Workbook { return &Workbook{ Worksheets: make([]*Worksheet, 0), Properties: &WorkbookProperties{ Created: time.Now(), Modified: time.Now(), Revision: 1, }, Relationships: NewRelationships(), Styles: NewStyles(), Theme: NewTheme(), ContentTypes: NewContentTypes(), Rels: NewWorkbookRels(), SharedStrings: NewSharedStrings(), } } // AddWorksheet 添加一个新的工作表 func (wb *Workbook) AddWorksheet(name string) *Worksheet { ws := NewWorksheet(name) ws.SheetID = len(wb.Worksheets) + 1 wb.Worksheets = append(wb.Worksheets, ws) return ws } // Save 保存Excel工作簿到文件 func (wb *Workbook) Save(filename string) error { // 创建一个新的zip文件 file, err := os.Create(filename) if err != nil { return err } defer file.Close() // 创建一个新的zip writer zipWriter := zip.NewWriter(file) defer zipWriter.Close() // 为每个工作表添加内容类型覆盖 for i := range wb.Worksheets { wb.ContentTypes.AddWorksheetOverride(i + 1) } // 添加[Content_Types].xml contentTypesWriter, err := zipWriter.Create("[Content_Types].xml") if err != nil { return err } _, err = contentTypesWriter.Write([]byte(wb.ContentTypes.ToXML())) if err != nil { return err } // 添加_rels/.rels relsDir, err := zipWriter.Create("_rels/.rels") if err != nil { return err } // 创建根关系 rootRels := NewRelationships() rootRels.AddRelationship("rId1", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", "xl/workbook.xml") _, err = relsDir.Write([]byte(rootRels.ToXML())) if err != nil { return err } // 添加xl/workbook.xml workbookWriter, err := zipWriter.Create("xl/workbook.xml") if err != nil { return err } _, err = workbookWriter.Write([]byte(wb.ToXML())) if err != nil { return err } // 添加xl/_rels/workbook.xml.rels workbookRelsWriter, err := zipWriter.Create("xl/_rels/workbook.xml.rels") if err != nil { return err } // 创建工作簿关系 wbRels := NewRelationships() // 添加样式关系 wbRels.AddRelationship("rId1", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", "styles.xml") // 添加主题关系 wbRels.AddRelationship("rId2", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml") // 添加共享字符串表关系 wbRels.AddRelationship("rId3", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", "sharedStrings.xml") // 添加工作表关系 for i := range wb.Worksheets { relID := fmt.Sprintf("rId%d", i+4) // 从rId4开始 target := fmt.Sprintf("worksheets/sheet%d.xml", i+1) wbRels.AddRelationship(relID, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", target) } _, err = workbookRelsWriter.Write([]byte(wbRels.ToXML())) if err != nil { return err } // 添加xl/worksheets/sheet1.xml, sheet2.xml, ... for i, ws := range wb.Worksheets { sheetPath := fmt.Sprintf("xl/worksheets/sheet%d.xml", i+1) sheetWriter, err := zipWriter.Create(sheetPath) if err != nil { return err } _, err = sheetWriter.Write([]byte(ws.ToXML(wb.SharedStrings))) if err != nil { return err } } // 添加xl/styles.xml stylesWriter, err := zipWriter.Create("xl/styles.xml") if err != nil { return err } _, err = stylesWriter.Write([]byte(wb.Styles.ToXML())) if err != nil { return err } // 添加xl/theme/theme1.xml themeWriter, err := zipWriter.Create("xl/theme/theme1.xml") if err != nil { return err } _, err = themeWriter.Write([]byte(wb.Theme.ToXML())) if err != nil { return err } // 添加xl/sharedStrings.xml sharedStringsWriter, err := zipWriter.Create("xl/sharedStrings.xml") if err != nil { return err } _, err = sharedStringsWriter.Write([]byte(wb.SharedStrings.ToXML())) if err != nil { return err } return nil } // WorkbookRels 表示工作簿的关系 type WorkbookRels struct { Relationships *Relationships } // NewWorkbookRels 创建一个新的工作簿关系 func NewWorkbookRels() *WorkbookRels { return &WorkbookRels{ Relationships: NewRelationships(), } } // ToXML 将工作簿转换为XML func (wb *Workbook) ToXML() string { xml := "\n" xml += "\n" // 工作簿属性 xml += " \n" // 工作表 xml += " \n" for i, ws := range wb.Worksheets { relID := fmt.Sprintf("rId%d", i+4) // 从rId4开始,与上面的关系ID对应 xml += fmt.Sprintf(" \n", ws.Name, ws.SheetID, relID) } xml += " \n" xml += "" return xml }