parent
2868bd3ec9
commit
46b8c46d91
@ -0,0 +1,170 @@
|
||||
package excelize
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// parseFormatTableSet provides function to parse the format settings of the
|
||||
// table with default value.
|
||||
func parseFormatTableSet(formatSet string) *formatTable {
|
||||
format := formatTable{
|
||||
TableStyle: "",
|
||||
ShowRowStripes: true,
|
||||
}
|
||||
json.Unmarshal([]byte(formatSet), &format)
|
||||
return &format
|
||||
}
|
||||
|
||||
// AddTable provides the method to add table in a worksheet by given sheet
|
||||
// index, coordinate area and format set. For example, create a table of A1:D5
|
||||
// on Sheet1:
|
||||
//
|
||||
// xlsx.AddTable("Sheet1", "A1", "D5", ``)
|
||||
//
|
||||
// Create a table of F2:H6 on Sheet2 with format set:
|
||||
//
|
||||
// xlsx.AddTable("Sheet2", "F2", "H6", `{"table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
|
||||
//
|
||||
// Note that the table at least two lines include string type header. The two
|
||||
// chart coordinate areas can not have an intersection.
|
||||
//
|
||||
// table_style: The built-in table style names
|
||||
//
|
||||
// TableStyleLight1 - TableStyleLight21
|
||||
// TableStyleMedium1 - TableStyleMedium28
|
||||
// TableStyleDark1 - TableStyleDark11
|
||||
//
|
||||
func (f *File) AddTable(sheet, hcell, vcell, format string) {
|
||||
formatSet := parseFormatTableSet(format)
|
||||
hcell = strings.ToUpper(hcell)
|
||||
vcell = strings.ToUpper(vcell)
|
||||
// Coordinate conversion, convert C1:B3 to 2,0,1,2.
|
||||
hcol := string(strings.Map(letterOnlyMapF, hcell))
|
||||
hrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, hcell))
|
||||
hyAxis := hrow - 1
|
||||
hxAxis := titleToNumber(hcol)
|
||||
|
||||
vcol := string(strings.Map(letterOnlyMapF, vcell))
|
||||
vrow, _ := strconv.Atoi(strings.Map(intOnlyMapF, vcell))
|
||||
vyAxis := vrow - 1
|
||||
vxAxis := titleToNumber(vcol)
|
||||
if vxAxis < hxAxis {
|
||||
hcell, vcell = vcell, hcell
|
||||
vxAxis, hxAxis = hxAxis, vxAxis
|
||||
}
|
||||
if vyAxis < hyAxis {
|
||||
hcell, vcell = vcell, hcell
|
||||
vyAxis, hyAxis = hyAxis, vyAxis
|
||||
}
|
||||
tableID := f.countTables() + 1
|
||||
sheetRelationshipsTableXML := "../tables/table" + strconv.Itoa(tableID) + ".xml"
|
||||
tableXML := strings.Replace(sheetRelationshipsTableXML, "..", "xl", -1)
|
||||
// Add first table for given sheet.
|
||||
rID := f.addSheetRelationships(sheet, SourceRelationshipTable, sheetRelationshipsTableXML, "")
|
||||
f.addSheetTable(sheet, rID)
|
||||
f.addTable(sheet, tableXML, hxAxis, hyAxis, vxAxis, vyAxis, tableID, formatSet)
|
||||
f.addTableContentTypePart(tableID)
|
||||
}
|
||||
|
||||
// countTables provides function to get table files count storage in the folder
|
||||
// xl/tables.
|
||||
func (f *File) countTables() int {
|
||||
count := 0
|
||||
for k := range f.XLSX {
|
||||
if strings.Contains(k, "xl/tables/table") {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// addSheetTable provides function to add tablePart element to
|
||||
// xl/worksheets/sheet%d.xml by given sheet name and relationship index.
|
||||
func (f *File) addSheetTable(sheet string, rID int) {
|
||||
xlsx := f.workSheetReader(sheet)
|
||||
table := &xlsxTablePart{
|
||||
RID: "rId" + strconv.Itoa(rID),
|
||||
}
|
||||
if xlsx.TableParts != nil {
|
||||
xlsx.TableParts.Count++
|
||||
xlsx.TableParts.TableParts = append(xlsx.TableParts.TableParts, table)
|
||||
} else {
|
||||
xlsx.TableParts = &xlsxTableParts{
|
||||
Count: 1,
|
||||
TableParts: []*xlsxTablePart{table},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// addTable provides function to add table by given sheet index, coordinate area
|
||||
// and format set.
|
||||
func (f *File) addTable(sheet, tableXML string, hxAxis, hyAxis, vxAxis, vyAxis, i int, formatSet *formatTable) {
|
||||
// Correct the minimum number of rows, the table at least two lines.
|
||||
if hyAxis == vyAxis {
|
||||
vyAxis++
|
||||
}
|
||||
// Correct table reference coordinate area, such correct C1:B3 to B1:C3.
|
||||
ref := toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
|
||||
tableColumn := []*xlsxTableColumn{}
|
||||
idx := 0
|
||||
for i := hxAxis; i <= vxAxis; i++ {
|
||||
idx++
|
||||
cell := toAlphaString(i+1) + strconv.Itoa(hyAxis+1)
|
||||
name := f.GetCellValue(sheet, cell)
|
||||
if _, err := strconv.Atoi(name); err == nil {
|
||||
f.SetCellStr(sheet, cell, name)
|
||||
}
|
||||
if name == "" {
|
||||
name = "Column" + strconv.Itoa(idx)
|
||||
f.SetCellStr(sheet, cell, name)
|
||||
}
|
||||
tableColumn = append(tableColumn, &xlsxTableColumn{
|
||||
ID: idx,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
name := "Table" + strconv.Itoa(i)
|
||||
t := xlsxTable{
|
||||
XMLNS: NameSpaceSpreadSheet,
|
||||
ID: i,
|
||||
Name: name,
|
||||
DisplayName: name,
|
||||
Ref: ref,
|
||||
AutoFilter: &xlsxAutoFilter{
|
||||
Ref: ref,
|
||||
},
|
||||
TableColumns: &xlsxTableColumns{
|
||||
Count: idx,
|
||||
TableColumn: tableColumn,
|
||||
},
|
||||
TableStyleInfo: &xlsxTableStyleInfo{
|
||||
Name: formatSet.TableStyle,
|
||||
ShowFirstColumn: formatSet.ShowFirstColumn,
|
||||
ShowLastColumn: formatSet.ShowLastColumn,
|
||||
ShowRowStripes: formatSet.ShowRowStripes,
|
||||
ShowColumnStripes: formatSet.ShowColumnStripes,
|
||||
},
|
||||
}
|
||||
table, _ := xml.Marshal(t)
|
||||
f.saveFileList(tableXML, string(table))
|
||||
}
|
||||
|
||||
// addTableContentTypePart provides function to add image part relationships
|
||||
// in the file [Content_Types].xml by given drawing index.
|
||||
func (f *File) addTableContentTypePart(index int) {
|
||||
f.setContentTypePartImageExtensions()
|
||||
content := f.contentTypesReader()
|
||||
for _, v := range content.Overrides {
|
||||
if v.PartName == "/xl/tables/table"+strconv.Itoa(index)+".xml" {
|
||||
return
|
||||
}
|
||||
}
|
||||
content.Overrides = append(content.Overrides, xlsxOverride{
|
||||
PartName: "/xl/tables/table" + strconv.Itoa(index) + ".xml",
|
||||
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml",
|
||||
})
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package excelize
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// xlsxTable directly maps the table element. A table helps organize and provide
|
||||
// structure to lists of information in a worksheet. Tables have clearly labeled
|
||||
// columns, rows, and data regions. Tables make it easier for users to sort,
|
||||
// analyze, format, manage, add, and delete information. This element is the
|
||||
// root element for a table that is not a single cell XML table.
|
||||
type xlsxTable struct {
|
||||
XMLName xml.Name `xml:"table"`
|
||||
XMLNS string `xml:"xmlns,attr"`
|
||||
DataCellStyle string `xml:"dataCellStyle,attr,omitempty"`
|
||||
DataDxfID int `xml:"dataDxfId,attr,omitempty"`
|
||||
DisplayName string `xml:"displayName,attr,omitempty"`
|
||||
HeaderRowBorderDxfID int `xml:"headerRowBorderDxfId,attr,omitempty"`
|
||||
HeaderRowCellStyle string `xml:"headerRowCellStyle,attr,omitempty"`
|
||||
HeaderRowCount int `xml:"headerRowCount,attr,omitempty"`
|
||||
HeaderRowDxfID int `xml:"headerRowDxfId,attr,omitempty"`
|
||||
ID int `xml:"id,attr"`
|
||||
InsertRow bool `xml:"insertRow,attr,omitempty"`
|
||||
InsertRowShift bool `xml:"insertRowShift,attr,omitempty"`
|
||||
Name string `xml:"name,attr"`
|
||||
Published bool `xml:"published,attr,omitempty"`
|
||||
Ref string `xml:"ref,attr"`
|
||||
TotalsRowCount int `xml:"totalsRowCount,attr,omitempty"`
|
||||
TotalsRowDxfID int `xml:"totalsRowDxfId,attr,omitempty"`
|
||||
TotalsRowShown bool `xml:"totalsRowShown,attr"`
|
||||
AutoFilter *xlsxAutoFilter `xml:"autoFilter"`
|
||||
TableColumns *xlsxTableColumns `xml:"tableColumns"`
|
||||
TableStyleInfo *xlsxTableStyleInfo `xml:"tableStyleInfo"`
|
||||
}
|
||||
|
||||
// xlsxAutoFilter temporarily hides rows based on a filter criteria, which is
|
||||
// applied column by column to a table of data in the worksheet. This collection
|
||||
// expresses AutoFilter settings.
|
||||
type xlsxAutoFilter struct {
|
||||
Ref string `xml:"ref,attr"`
|
||||
}
|
||||
|
||||
// xlsxTableColumns directly maps the element representing the collection of all
|
||||
// table columns for this table.
|
||||
type xlsxTableColumns struct {
|
||||
Count int `xml:"count,attr"`
|
||||
TableColumn []*xlsxTableColumn `xml:"tableColumn"`
|
||||
}
|
||||
|
||||
// xlsxTableColumn directly maps the element representing a single column for
|
||||
// this table.
|
||||
type xlsxTableColumn struct {
|
||||
DataCellStyle string `xml:"dataCellStyle,attr,omitempty"`
|
||||
DataDxfID int `xml:"dataDxfId,attr,omitempty"`
|
||||
HeaderRowCellStyle string `xml:"headerRowCellStyle,attr,omitempty"`
|
||||
HeaderRowDxfID int `xml:"headerRowDxfId,attr,omitempty"`
|
||||
ID int `xml:"id,attr"`
|
||||
Name string `xml:"name,attr"`
|
||||
QueryTableFieldID int `xml:"queryTableFieldId,attr,omitempty"`
|
||||
TotalsRowCellStyle string `xml:"totalsRowCellStyle,attr,omitempty"`
|
||||
TotalsRowDxfID int `xml:"totalsRowDxfId,attr,omitempty"`
|
||||
TotalsRowFunction string `xml:"totalsRowFunction,attr,omitempty"`
|
||||
TotalsRowLabel string `xml:"totalsRowLabel,attr,omitempty"`
|
||||
UniqueName string `xml:"uniqueName,attr,omitempty"`
|
||||
}
|
||||
|
||||
// xlsxTableStyleInfo directly maps the tableStyleInfo element. This element
|
||||
// describes which style is used to display this table, and specifies which
|
||||
// portions of the table have the style applied.
|
||||
type xlsxTableStyleInfo struct {
|
||||
Name string `xml:"name,attr,omitempty"`
|
||||
ShowFirstColumn bool `xml:"showFirstColumn,attr"`
|
||||
ShowLastColumn bool `xml:"showLastColumn,attr"`
|
||||
ShowRowStripes bool `xml:"showRowStripes,attr"`
|
||||
ShowColumnStripes bool `xml:"showColumnStripes,attr"`
|
||||
}
|
||||
|
||||
// formatTable directly maps the format settings of the table.
|
||||
type formatTable struct {
|
||||
TableStyle string `json:"table_style"`
|
||||
ShowFirstColumn bool `json:"show_first_column"`
|
||||
ShowLastColumn bool `json:"show_last_column"`
|
||||
ShowRowStripes bool `json:"show_row_stripes"`
|
||||
ShowColumnStripes bool `json:"show_column_stripes"`
|
||||
}
|
Loading…
Reference in new issue