2017-04-28 15:49:41 +08:00
|
|
|
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 {
|
|
|
|
vxAxis, hxAxis = hxAxis, vxAxis
|
|
|
|
}
|
|
|
|
if vyAxis < hyAxis {
|
|
|
|
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)
|
2017-05-24 14:17:35 +08:00
|
|
|
f.addContentTypePart(tableID, "table")
|
2017-04-28 15:49:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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))
|
|
|
|
}
|