forked from p30928647/excelize
Format code, update documentation and remove exported variable `XMLHeaderByte`
This commit is contained in:
parent
139ee4c4b0
commit
8a335225c7
|
@ -4629,7 +4629,7 @@ func TestCalcLogBeta(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCalcBetainvProbIterator(t *testing.T) {
|
func TestCalcBetainvProbIterator(t *testing.T) {
|
||||||
assert.Equal(t, 1.0, betainvProbIterator(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true))
|
assert.Equal(t, 1.0, betainvProbIterator(1, 1, 1, 1, 1, 1, 1, 1, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNestedFunctionsWithOperators(t *testing.T) {
|
func TestNestedFunctionsWithOperators(t *testing.T) {
|
||||||
|
|
53
cell.go
53
cell.go
|
@ -200,7 +200,7 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ func (f *File) SetCellInt(sheet, axis string, value int) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ func setCellBool(value bool) (t string, v string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCellFloat sets a floating point value into a cell. The prec parameter
|
// SetCellFloat sets a floating point value into a cell. The precision parameter
|
||||||
// specifies how many places after the decimal will be shown while -1 is a
|
// specifies how many places after the decimal will be shown while -1 is a
|
||||||
// special value that will use as many decimal places as necessary to
|
// special value that will use as many decimal places as necessary to
|
||||||
// represent the number. bitSize is 32 or 64 depending on if a float32 or
|
// represent the number. bitSize is 32 or 64 depending on if a float32 or
|
||||||
|
@ -308,26 +308,26 @@ func setCellBool(value bool) (t string, v string) {
|
||||||
// var x float32 = 1.325
|
// var x float32 = 1.325
|
||||||
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
||||||
//
|
//
|
||||||
func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) error {
|
func (f *File) SetCellFloat(sheet, axis string, value float64, precision, bitSize int) error {
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ws.Lock()
|
ws.Lock()
|
||||||
defer ws.Unlock()
|
defer ws.Unlock()
|
||||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||||
cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
|
cellData.T, cellData.V = setCellFloat(value, precision, bitSize)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// setCellFloat prepares cell type and string type cell value by a given
|
// setCellFloat prepares cell type and string type cell value by a given
|
||||||
// float value.
|
// float value.
|
||||||
func setCellFloat(value float64, prec, bitSize int) (t string, v string) {
|
func setCellFloat(value float64, precision, bitSize int) (t string, v string) {
|
||||||
v = strconv.FormatFloat(value, 'f', prec, bitSize)
|
v = strconv.FormatFloat(value, 'f', precision, bitSize)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -436,7 +436,7 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,7 @@ type FormulaOpts struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCellFormula provides a function to set formula on the cell is taken
|
// SetCellFormula provides a function to set formula on the cell is taken
|
||||||
// according to the given worksheet name (case sensitive) and cell formula
|
// according to the given worksheet name (case-sensitive) and cell formula
|
||||||
// settings. The result of the formula cell can be calculated when the
|
// settings. The result of the formula cell can be calculated when the
|
||||||
// worksheet is opened by the Office Excel application or can be using
|
// worksheet is opened by the Office Excel application or can be using
|
||||||
// the "CalcCellValue" function also can get the calculated cell value. If
|
// the "CalcCellValue" function also can get the calculated cell value. If
|
||||||
|
@ -560,7 +560,7 @@ func (f *File) SetCellFormula(sheet, axis, formula string, opts ...FormulaOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, _, _, err := f.prepareCell(ws, sheet, axis)
|
cellData, _, _, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -673,11 +673,8 @@ type HyperlinkOpts struct {
|
||||||
// SetCellHyperLink provides a function to set cell hyperlink by given
|
// SetCellHyperLink provides a function to set cell hyperlink by given
|
||||||
// worksheet name and link URL address. LinkType defines two types of
|
// worksheet name and link URL address. LinkType defines two types of
|
||||||
// hyperlink "External" for website or "Location" for moving to one of cell
|
// hyperlink "External" for website or "Location" for moving to one of cell
|
||||||
// in this workbook. Maximum limit hyperlinks in a worksheet is 65530. This
|
// in this workbook. Maximum limit hyperlinks in a worksheet is 65530. The
|
||||||
// function is only used to set the hyperlink of the cell and doesn't affect
|
// below is example for external link.
|
||||||
// the value of the cell. If you need to set the value of the cell, please use
|
|
||||||
// the other functions such as `SetCellStyle` or `SetSheetRow`. The below is
|
|
||||||
// example for external link.
|
|
||||||
//
|
//
|
||||||
// if err := f.SetCellHyperLink("Sheet1", "A3",
|
// if err := f.SetCellHyperLink("Sheet1", "A3",
|
||||||
// "https://github.com/xuri/excelize", "External"); err != nil {
|
// "https://github.com/xuri/excelize", "External"); err != nil {
|
||||||
|
@ -692,7 +689,7 @@ type HyperlinkOpts struct {
|
||||||
// }
|
// }
|
||||||
// err = f.SetCellStyle("Sheet1", "A3", "A3", style)
|
// err = f.SetCellStyle("Sheet1", "A3", "A3", style)
|
||||||
//
|
//
|
||||||
// A this is another example for "Location":
|
// This is another example for "Location":
|
||||||
//
|
//
|
||||||
// err := f.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
|
// err := f.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
|
||||||
//
|
//
|
||||||
|
@ -759,7 +756,7 @@ func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cellData, _, _, err := f.prepareCell(ws, sheet, cell)
|
cellData, _, _, err := f.prepareCell(ws, cell)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -940,7 +937,7 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, cell)
|
cellData, col, row, err := f.prepareCell(ws, cell)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -950,7 +947,7 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
|
||||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||||
si := xlsxSI{}
|
si := xlsxSI{}
|
||||||
sst := f.sharedStringsReader()
|
sst := f.sharedStringsReader()
|
||||||
textRuns := []xlsxR{}
|
var textRuns []xlsxR
|
||||||
totalCellChars := 0
|
totalCellChars := 0
|
||||||
for _, textRun := range runs {
|
for _, textRun := range runs {
|
||||||
totalCellChars += len(textRun.Text)
|
totalCellChars += len(textRun.Text)
|
||||||
|
@ -1000,8 +997,8 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
|
||||||
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
cell, err := CoordinatesToCellName(col+i, row)
|
cell, err := CoordinatesToCellName(col+i, row)
|
||||||
// Error should never happens here. But keep checking to early detect regresions
|
// Error should never happen here. But keep checking to early detect regressions
|
||||||
// if it will be introduced in future.
|
// if it will be introduced in the future.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1013,7 +1010,7 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCellInfo does common preparation for all SetCell* methods.
|
// getCellInfo does common preparation for all SetCell* methods.
|
||||||
func (f *File) prepareCell(ws *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int, error) {
|
func (f *File) prepareCell(ws *xlsxWorksheet, cell string) (*xlsxC, int, int, error) {
|
||||||
var err error
|
var err error
|
||||||
cell, err = f.mergeCellsParser(ws, cell)
|
cell, err = f.mergeCellsParser(ws, cell)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1175,7 +1172,7 @@ func (f *File) checkCellInArea(cell, area string) (bool, error) {
|
||||||
return cellInRef([]int{col, row}, coordinates), err
|
return cellInRef([]int{col, row}, coordinates), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// cellInRef provides a function to determine if a given range is within an
|
// cellInRef provides a function to determine if a given range is within a
|
||||||
// range.
|
// range.
|
||||||
func cellInRef(cell, ref []int) bool {
|
func cellInRef(cell, ref []int) bool {
|
||||||
return cell[0] >= ref[0] && cell[0] <= ref[2] && cell[1] >= ref[1] && cell[1] <= ref[3]
|
return cell[0] >= ref[0] && cell[0] <= ref[2] && cell[1] >= ref[1] && cell[1] <= ref[3]
|
||||||
|
@ -1241,7 +1238,7 @@ func parseSharedFormula(dCol, dRow int, orig []byte) (res string, start int) {
|
||||||
// considered to be the same when their respective representations in
|
// considered to be the same when their respective representations in
|
||||||
// R1C1-reference notation, are the same.
|
// R1C1-reference notation, are the same.
|
||||||
//
|
//
|
||||||
// Note that this function not validate ref tag to check the cell if or not in
|
// Note that this function not validate ref tag to check the cell whether in
|
||||||
// allow area, and always return origin shared formula.
|
// allow area, and always return origin shared formula.
|
||||||
func getSharedFormula(ws *xlsxWorksheet, si int, axis string) string {
|
func getSharedFormula(ws *xlsxWorksheet, si int, axis string) string {
|
||||||
for _, r := range ws.SheetData.Row {
|
for _, r := range ws.SheetData.Row {
|
||||||
|
@ -1264,7 +1261,7 @@ func getSharedFormula(ws *xlsxWorksheet, si int, axis string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// shiftCell returns the cell shifted according to dCol and dRow taking into
|
// shiftCell returns the cell shifted according to dCol and dRow taking into
|
||||||
// consideration of absolute references with dollar sign ($)
|
// consideration absolute references with dollar sign ($)
|
||||||
func shiftCell(cellID string, dCol, dRow int) string {
|
func shiftCell(cellID string, dCol, dRow int) string {
|
||||||
fCol, fRow, _ := CellNameToCoordinates(cellID)
|
fCol, fRow, _ := CellNameToCoordinates(cellID)
|
||||||
signCol, signRow := "", ""
|
signCol, signRow := "", ""
|
||||||
|
|
|
@ -33,7 +33,7 @@ func TestConcurrency(t *testing.T) {
|
||||||
assert.NoError(t, f.SetSheetRow("Sheet1", "B6", &[]interface{}{
|
assert.NoError(t, f.SetSheetRow("Sheet1", "B6", &[]interface{}{
|
||||||
" Hello",
|
" Hello",
|
||||||
[]byte("World"), 42, int8(1<<8/2 - 1), int16(1<<16/2 - 1), int32(1<<32/2 - 1),
|
[]byte("World"), 42, int8(1<<8/2 - 1), int16(1<<16/2 - 1), int32(1<<32/2 - 1),
|
||||||
int64(1<<32/2 - 1), float32(42.65418), float64(-42.65418), float32(42), float64(42),
|
int64(1<<32/2 - 1), float32(42.65418), -42.65418, float32(42), float64(42),
|
||||||
uint(1<<32 - 1), uint8(1<<8 - 1), uint16(1<<16 - 1), uint32(1<<32 - 1),
|
uint(1<<32 - 1), uint8(1<<8 - 1), uint16(1<<16 - 1), uint32(1<<32 - 1),
|
||||||
uint64(1<<32 - 1), true, complex64(5 + 10i),
|
uint64(1<<32 - 1), true, complex64(5 + 10i),
|
||||||
}))
|
}))
|
||||||
|
|
2
chart.go
2
chart.go
|
@ -969,7 +969,7 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error {
|
||||||
// getFormatChart provides a function to check format set of the chart and
|
// getFormatChart provides a function to check format set of the chart and
|
||||||
// create chart format.
|
// create chart format.
|
||||||
func (f *File) getFormatChart(format string, combo []string) (*formatChart, []*formatChart, error) {
|
func (f *File) getFormatChart(format string, combo []string) (*formatChart, []*formatChart, error) {
|
||||||
comboCharts := []*formatChart{}
|
var comboCharts []*formatChart
|
||||||
formatSet, err := parseFormatChartSet(format)
|
formatSet, err := parseFormatChartSet(format)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return formatSet, comboCharts, err
|
return formatSet, comboCharts, err
|
||||||
|
|
|
@ -353,7 +353,7 @@ func TestChartWithLogarithmicBase(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.True(t, ok, "Can't open the %s", chartPath)
|
assert.True(t, ok, "Can't open the %s", chartPath)
|
||||||
|
|
||||||
err = xml.Unmarshal([]byte(xmlCharts[i]), &chartSpaces[i])
|
err = xml.Unmarshal(xmlCharts[i], &chartSpaces[i])
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
21
col.go
21
col.go
|
@ -40,8 +40,7 @@ type Cols struct {
|
||||||
sheetXML []byte
|
sheetXML []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCols return all the columns in a sheet by given worksheet name (case
|
// GetCols return all the columns in a sheet by given worksheet name (case-sensitive). For example:
|
||||||
// sensitive). For example:
|
|
||||||
//
|
//
|
||||||
// cols, err := f.GetCols("Sheet1")
|
// cols, err := f.GetCols("Sheet1")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
|
@ -240,20 +239,18 @@ func (f *File) Cols(sheet string) (*Cols, error) {
|
||||||
// visible, err := f.GetColVisible("Sheet1", "D")
|
// visible, err := f.GetColVisible("Sheet1", "D")
|
||||||
//
|
//
|
||||||
func (f *File) GetColVisible(sheet, col string) (bool, error) {
|
func (f *File) GetColVisible(sheet, col string) (bool, error) {
|
||||||
visible := true
|
|
||||||
colNum, err := ColumnNameToNumber(col)
|
colNum, err := ColumnNameToNumber(col)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return visible, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if ws.Cols == nil {
|
if ws.Cols == nil {
|
||||||
return visible, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
visible := true
|
||||||
for c := range ws.Cols.Col {
|
for c := range ws.Cols.Col {
|
||||||
colData := &ws.Cols.Col[c]
|
colData := &ws.Cols.Col[c]
|
||||||
if colData.Min <= colNum && colNum <= colData.Max {
|
if colData.Min <= colNum && colNum <= colData.Max {
|
||||||
|
@ -455,12 +452,12 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
|
||||||
// f := excelize.NewFile()
|
// f := excelize.NewFile()
|
||||||
// err := f.SetColWidth("Sheet1", "A", "H", 20)
|
// err := f.SetColWidth("Sheet1", "A", "H", 20)
|
||||||
//
|
//
|
||||||
func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error {
|
func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error {
|
||||||
min, err := ColumnNameToNumber(startcol)
|
min, err := ColumnNameToNumber(startCol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
max, err := ColumnNameToNumber(endcol)
|
max, err := ColumnNameToNumber(endCol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -502,7 +499,7 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error
|
||||||
// flatCols provides a method for the column's operation functions to flatten
|
// flatCols provides a method for the column's operation functions to flatten
|
||||||
// and check the worksheet columns.
|
// and check the worksheet columns.
|
||||||
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
|
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
|
||||||
fc := []xlsxCol{}
|
var fc []xlsxCol
|
||||||
for i := col.Min; i <= col.Max; i++ {
|
for i := col.Min; i <= col.Max; i++ {
|
||||||
c := deepcopy.Copy(col).(xlsxCol)
|
c := deepcopy.Copy(col).(xlsxCol)
|
||||||
c.Min, c.Max = i, i
|
c.Min, c.Max = i, i
|
||||||
|
@ -547,7 +544,7 @@ func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol)
|
||||||
// | | | (x2,y2)|
|
// | | | (x2,y2)|
|
||||||
// +-----+------------+------------+
|
// +-----+------------+------------+
|
||||||
//
|
//
|
||||||
// Example of an object that covers some of the area from cell A1 to B2.
|
// Example of an object that covers some area from cell A1 to B2.
|
||||||
//
|
//
|
||||||
// Based on the width and height of the object we need to calculate 8 vars:
|
// Based on the width and height of the object we need to calculate 8 vars:
|
||||||
//
|
//
|
||||||
|
|
|
@ -47,7 +47,7 @@ func (f *File) GetComments() (comments map[string][]Comment) {
|
||||||
target = "xl" + strings.TrimPrefix(target, "..")
|
target = "xl" + strings.TrimPrefix(target, "..")
|
||||||
}
|
}
|
||||||
if d := f.commentsReader(strings.TrimPrefix(target, "/")); d != nil {
|
if d := f.commentsReader(strings.TrimPrefix(target, "/")); d != nil {
|
||||||
sheetComments := []Comment{}
|
var sheetComments []Comment
|
||||||
for _, comment := range d.CommentList.Comment {
|
for _, comment := range d.CommentList.Comment {
|
||||||
sheetComment := Comment{}
|
sheetComment := Comment{}
|
||||||
if comment.AuthorID < len(d.Authors.Author) {
|
if comment.AuthorID < len(d.Authors.Author) {
|
||||||
|
|
6
crypt.go
6
crypt.go
|
@ -629,7 +629,7 @@ func genISOPasswdHash(passwd, hashAlgorithm, salt string, spinCount int) (hashVa
|
||||||
err = ErrPasswordLengthInvalid
|
err = ErrPasswordLengthInvalid
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hash, ok := map[string]string{
|
algorithmName, ok := map[string]string{
|
||||||
"MD4": "md4",
|
"MD4": "md4",
|
||||||
"MD5": "md5",
|
"MD5": "md5",
|
||||||
"SHA-1": "sha1",
|
"SHA-1": "sha1",
|
||||||
|
@ -653,11 +653,11 @@ func genISOPasswdHash(passwd, hashAlgorithm, salt string, spinCount int) (hashVa
|
||||||
passwordBuffer, _ := encoder.Bytes([]byte(passwd))
|
passwordBuffer, _ := encoder.Bytes([]byte(passwd))
|
||||||
b.Write(passwordBuffer)
|
b.Write(passwordBuffer)
|
||||||
// Generate the initial hash.
|
// Generate the initial hash.
|
||||||
key := hashing(hash, b.Bytes())
|
key := hashing(algorithmName, b.Bytes())
|
||||||
// Now regenerate until spin count.
|
// Now regenerate until spin count.
|
||||||
for i := 0; i < spinCount; i++ {
|
for i := 0; i < spinCount; i++ {
|
||||||
iterator := createUInt32LEBuffer(i, 4)
|
iterator := createUInt32LEBuffer(i, 4)
|
||||||
key = hashing(hash, key, iterator)
|
key = hashing(algorithmName, key, iterator)
|
||||||
}
|
}
|
||||||
hashValue, saltValue = base64.StdEncoding.EncodeToString(key), base64.StdEncoding.EncodeToString(s)
|
hashValue, saltValue = base64.StdEncoding.EncodeToString(key), base64.StdEncoding.EncodeToString(s)
|
||||||
return
|
return
|
||||||
|
|
|
@ -34,7 +34,7 @@ func TestEncryptionMechanism(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHashing(t *testing.T) {
|
func TestHashing(t *testing.T) {
|
||||||
assert.Equal(t, hashing("unsupportedHashAlgorithm", []byte{}), []uint8([]byte(nil)))
|
assert.Equal(t, hashing("unsupportedHashAlgorithm", []byte{}), []byte(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenISOPasswdHash(t *testing.T) {
|
func TestGenISOPasswdHash(t *testing.T) {
|
||||||
|
|
|
@ -129,27 +129,27 @@ func (dd *DataValidation) SetRange(f1, f2 interface{}, t DataValidationType, o D
|
||||||
var formula1, formula2 string
|
var formula1, formula2 string
|
||||||
switch v := f1.(type) {
|
switch v := f1.(type) {
|
||||||
case int:
|
case int:
|
||||||
formula1 = fmt.Sprintf("<formula1>%d</formula1>", int(v))
|
formula1 = fmt.Sprintf("<formula1>%d</formula1>", v)
|
||||||
case float64:
|
case float64:
|
||||||
if math.Abs(float64(v)) > math.MaxFloat32 {
|
if math.Abs(v) > math.MaxFloat32 {
|
||||||
return ErrDataValidationRange
|
return ErrDataValidationRange
|
||||||
}
|
}
|
||||||
formula1 = fmt.Sprintf("<formula1>%.17g</formula1>", float64(v))
|
formula1 = fmt.Sprintf("<formula1>%.17g</formula1>", v)
|
||||||
case string:
|
case string:
|
||||||
formula1 = fmt.Sprintf("<formula1>%s</formula1>", string(v))
|
formula1 = fmt.Sprintf("<formula1>%s</formula1>", v)
|
||||||
default:
|
default:
|
||||||
return ErrParameterInvalid
|
return ErrParameterInvalid
|
||||||
}
|
}
|
||||||
switch v := f2.(type) {
|
switch v := f2.(type) {
|
||||||
case int:
|
case int:
|
||||||
formula2 = fmt.Sprintf("<formula2>%d</formula2>", int(v))
|
formula2 = fmt.Sprintf("<formula2>%d</formula2>", v)
|
||||||
case float64:
|
case float64:
|
||||||
if math.Abs(float64(v)) > math.MaxFloat32 {
|
if math.Abs(v) > math.MaxFloat32 {
|
||||||
return ErrDataValidationRange
|
return ErrDataValidationRange
|
||||||
}
|
}
|
||||||
formula2 = fmt.Sprintf("<formula2>%.17g</formula2>", float64(v))
|
formula2 = fmt.Sprintf("<formula2>%.17g</formula2>", v)
|
||||||
case string:
|
case string:
|
||||||
formula2 = fmt.Sprintf("<formula2>%s</formula2>", string(v))
|
formula2 = fmt.Sprintf("<formula2>%s</formula2>", v)
|
||||||
default:
|
default:
|
||||||
return ErrParameterInvalid
|
return ErrParameterInvalid
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ func (f *File) DeleteDataValidation(sheet, sqref string) error {
|
||||||
}
|
}
|
||||||
dv := ws.DataValidations
|
dv := ws.DataValidations
|
||||||
for i := 0; i < len(dv.DataValidation); i++ {
|
for i := 0; i < len(dv.DataValidation); i++ {
|
||||||
applySqref := []string{}
|
var applySqref []string
|
||||||
colCells, err := f.flatSqref(dv.DataValidation[i].Sqref)
|
colCells, err := f.flatSqref(dv.DataValidation[i].Sqref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -314,7 +314,8 @@ func (f *File) squashSqref(cells [][]int) []string {
|
||||||
} else if len(cells) == 0 {
|
} else if len(cells) == 0 {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
l, r, res := 0, 0, []string{}
|
var res []string
|
||||||
|
l, r := 0, 0
|
||||||
for i := 1; i < len(cells); i++ {
|
for i := 1; i < len(cells); i++ {
|
||||||
if cells[i][0] == cells[r][0] && cells[i][1]-cells[r][1] > 1 {
|
if cells[i][0] == cells[r][0] && cells[i][1]-cells[r][1] > 1 {
|
||||||
curr, _ := f.coordinatesToAreaRef(append(cells[l], cells[r]...))
|
curr, _ := f.coordinatesToAreaRef(append(cells[l], cells[r]...))
|
||||||
|
|
|
@ -740,7 +740,7 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
|
||||||
// drawChartSeries provides a function to draw the c:ser element by given
|
// drawChartSeries provides a function to draw the c:ser element by given
|
||||||
// format sets.
|
// format sets.
|
||||||
func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
|
func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
|
||||||
ser := []cSer{}
|
var ser []cSer
|
||||||
for k := range formatSet.Series {
|
for k := range formatSet.Series {
|
||||||
ser = append(ser, cSer{
|
ser = append(ser, cSer{
|
||||||
IDx: &attrValInt{Val: intPtr(k + formatSet.order)},
|
IDx: &attrValInt{Val: intPtr(k + formatSet.order)},
|
||||||
|
|
|
@ -138,9 +138,9 @@ var (
|
||||||
// ErrDefinedNameScope defined the error message on not found defined name
|
// ErrDefinedNameScope defined the error message on not found defined name
|
||||||
// in the given scope.
|
// in the given scope.
|
||||||
ErrDefinedNameScope = errors.New("no defined name on the scope")
|
ErrDefinedNameScope = errors.New("no defined name on the scope")
|
||||||
// ErrDefinedNameduplicate defined the error message on the same name
|
// ErrDefinedNameDuplicate defined the error message on the same name
|
||||||
// already exists on the scope.
|
// already exists on the scope.
|
||||||
ErrDefinedNameduplicate = errors.New("the same name already exists on the scope")
|
ErrDefinedNameDuplicate = errors.New("the same name already exists on the scope")
|
||||||
// ErrCustomNumFmt defined the error message on receive the empty custom number format.
|
// ErrCustomNumFmt defined the error message on receive the empty custom number format.
|
||||||
ErrCustomNumFmt = errors.New("custom number format can not be empty")
|
ErrCustomNumFmt = errors.New("custom number format can not be empty")
|
||||||
// ErrFontLength defined the error message on the length of the font
|
// ErrFontLength defined the error message on the length of the font
|
||||||
|
|
|
@ -102,13 +102,16 @@ func OpenFile(filename string, opt ...Options) (*File, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
|
||||||
f, err := OpenReader(file, opt...)
|
f, err := OpenReader(file, opt...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
closeErr := file.Close()
|
||||||
|
if closeErr == nil {
|
||||||
|
return f, err
|
||||||
|
}
|
||||||
|
return f, closeErr
|
||||||
}
|
}
|
||||||
f.Path = filename
|
f.Path = filename
|
||||||
return f, nil
|
return f, file.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFile is object builder
|
// newFile is object builder
|
||||||
|
|
|
@ -40,11 +40,11 @@ func TestOpenFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.NoError(t, f.UpdateLinkedValue())
|
assert.NoError(t, f.UpdateLinkedValue())
|
||||||
|
|
||||||
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32)))
|
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(100.1588, 'f', -1, 32)))
|
||||||
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)))
|
assert.NoError(t, f.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(-100.1588, 'f', -1, 64)))
|
||||||
|
|
||||||
// Test set cell value with illegal row number.
|
// Test set cell value with illegal row number.
|
||||||
assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)),
|
assert.EqualError(t, f.SetCellDefault("Sheet2", "A", strconv.FormatFloat(-100.1588, 'f', -1, 64)),
|
||||||
newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
|
||||||
|
|
||||||
assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
|
assert.NoError(t, f.SetCellInt("Sheet2", "A1", 100))
|
||||||
|
@ -109,7 +109,7 @@ func TestOpenFile(t *testing.T) {
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F5", int32(1<<32/2-1)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F5", int32(1<<32/2-1)))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F6", int64(1<<32/2-1)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F6", int64(1<<32/2-1)))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F7", float32(42.65418)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F7", float32(42.65418)))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F8", float64(-42.65418)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F8", -42.65418))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F9", float32(42)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F9", float32(42)))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F10", float64(42)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F10", float64(42)))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet2", "F11", uint(1<<32-1)))
|
assert.NoError(t, f.SetCellValue("Sheet2", "F11", uint(1<<32-1)))
|
||||||
|
@ -1157,9 +1157,9 @@ func TestHSL(t *testing.T) {
|
||||||
assert.Equal(t, 0.0, hueToRGB(0, 0, 2.0/4))
|
assert.Equal(t, 0.0, hueToRGB(0, 0, 2.0/4))
|
||||||
t.Log(RGBToHSL(255, 255, 0))
|
t.Log(RGBToHSL(255, 255, 0))
|
||||||
h, s, l := RGBToHSL(0, 255, 255)
|
h, s, l := RGBToHSL(0, 255, 255)
|
||||||
assert.Equal(t, float64(0.5), h)
|
assert.Equal(t, 0.5, h)
|
||||||
assert.Equal(t, float64(1), s)
|
assert.Equal(t, 1.0, s)
|
||||||
assert.Equal(t, float64(0.5), l)
|
assert.Equal(t, 0.5, l)
|
||||||
t.Log(RGBToHSL(250, 100, 50))
|
t.Log(RGBToHSL(250, 100, 50))
|
||||||
t.Log(RGBToHSL(50, 100, 250))
|
t.Log(RGBToHSL(50, 100, 250))
|
||||||
t.Log(RGBToHSL(250, 50, 100))
|
t.Log(RGBToHSL(250, 50, 100))
|
||||||
|
|
24
lib.go
24
lib.go
|
@ -80,11 +80,14 @@ func (f *File) unzipToTemp(zipFile *zip.File) (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tmp.Name(), err
|
return tmp.Name(), err
|
||||||
}
|
}
|
||||||
_, err = io.Copy(tmp, rc)
|
if _, err = io.Copy(tmp, rc); err != nil {
|
||||||
rc.Close()
|
|
||||||
tmp.Close()
|
|
||||||
return tmp.Name(), err
|
return tmp.Name(), err
|
||||||
}
|
}
|
||||||
|
if err = rc.Close(); err != nil {
|
||||||
|
return tmp.Name(), err
|
||||||
|
}
|
||||||
|
return tmp.Name(), tmp.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// readXML provides a function to read XML content as bytes.
|
// readXML provides a function to read XML content as bytes.
|
||||||
func (f *File) readXML(name string) []byte {
|
func (f *File) readXML(name string) []byte {
|
||||||
|
@ -109,7 +112,7 @@ func (f *File) readBytes(name string) []byte {
|
||||||
}
|
}
|
||||||
content, _ = ioutil.ReadAll(file)
|
content, _ = ioutil.ReadAll(file)
|
||||||
f.Pkg.Store(name, content)
|
f.Pkg.Store(name, content)
|
||||||
file.Close()
|
_ = file.Close()
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,9 +440,10 @@ func (avb attrValBool) MarshalXML(e *xml.Encoder, start xml.StartElement) error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start.Attr = []xml.Attr{attr}
|
start.Attr = []xml.Attr{attr}
|
||||||
e.EncodeToken(start)
|
if err := e.EncodeToken(start); err != nil {
|
||||||
e.EncodeToken(start.End())
|
return err
|
||||||
return nil
|
}
|
||||||
|
return e.EncodeToken(start.End())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalXML convert the literal values true, false, 1, 0 of the XML
|
// UnmarshalXML convert the literal values true, false, 1, 0 of the XML
|
||||||
|
@ -558,7 +562,7 @@ func genSheetPasswd(plaintext string) string {
|
||||||
charPos++
|
charPos++
|
||||||
rotatedBits := value >> 15 // rotated bits beyond bit 15
|
rotatedBits := value >> 15 // rotated bits beyond bit 15
|
||||||
value &= 0x7fff // first 15 bits
|
value &= 0x7fff // first 15 bits
|
||||||
password ^= (value | rotatedBits)
|
password ^= value | rotatedBits
|
||||||
}
|
}
|
||||||
password ^= int64(len(plaintext))
|
password ^= int64(len(plaintext))
|
||||||
password ^= 0xCE4B
|
password ^= 0xCE4B
|
||||||
|
@ -793,8 +797,8 @@ type Stack struct {
|
||||||
|
|
||||||
// NewStack create a new stack.
|
// NewStack create a new stack.
|
||||||
func NewStack() *Stack {
|
func NewStack() *Stack {
|
||||||
list := list.New()
|
l := list.New()
|
||||||
return &Stack{list}
|
return &Stack{l}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push a value onto the top of the stack.
|
// Push a value onto the top of the stack.
|
||||||
|
|
|
@ -23,7 +23,7 @@ func TestMergeCell(t *testing.T) {
|
||||||
assert.NoError(t, f.MergeCell("Sheet1", "G10", "K12"))
|
assert.NoError(t, f.MergeCell("Sheet1", "G10", "K12"))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet1", "G11", "set value in merged cell"))
|
assert.NoError(t, f.SetCellValue("Sheet1", "G11", "set value in merged cell"))
|
||||||
assert.NoError(t, f.SetCellInt("Sheet1", "H11", 100))
|
assert.NoError(t, f.SetCellInt("Sheet1", "H11", 100))
|
||||||
assert.NoError(t, f.SetCellValue("Sheet1", "I11", float64(0.5)))
|
assert.NoError(t, f.SetCellValue("Sheet1", "I11", 0.5))
|
||||||
assert.NoError(t, f.SetCellHyperLink("Sheet1", "J11", "https://github.com/xuri/excelize", "External"))
|
assert.NoError(t, f.SetCellHyperLink("Sheet1", "J11", "https://github.com/xuri/excelize", "External"))
|
||||||
assert.NoError(t, f.SetCellFormula("Sheet1", "G12", "SUM(Sheet1!B19,Sheet1!C19)"))
|
assert.NoError(t, f.SetCellFormula("Sheet1", "G12", "SUM(Sheet1!B19,Sheet1!C19)"))
|
||||||
value, err := f.GetCellValue("Sheet1", "H11")
|
value, err := f.GetCellValue("Sheet1", "H11")
|
||||||
|
|
10
numfmt.go
10
numfmt.go
|
@ -456,7 +456,7 @@ func localMonthsNameIrish(t time.Time, abbr int) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if abbr == 4 {
|
if abbr == 4 {
|
||||||
return string([]rune(monthNamesIrish[int(t.Month())-1]))
|
return monthNamesIrish[int(t.Month())-1]
|
||||||
}
|
}
|
||||||
return string([]rune(monthNamesIrish[int(t.Month())-1])[:1])
|
return string([]rune(monthNamesIrish[int(t.Month())-1])[:1])
|
||||||
}
|
}
|
||||||
|
@ -536,7 +536,7 @@ func localMonthsNameRussian(t time.Time, abbr int) string {
|
||||||
return string([]rune(month)[:3]) + "."
|
return string([]rune(month)[:3]) + "."
|
||||||
}
|
}
|
||||||
if abbr == 4 {
|
if abbr == 4 {
|
||||||
return string([]rune(monthNamesRussian[int(t.Month())-1]))
|
return monthNamesRussian[int(t.Month())-1]
|
||||||
}
|
}
|
||||||
return string([]rune(monthNamesRussian[int(t.Month())-1])[:1])
|
return string([]rune(monthNamesRussian[int(t.Month())-1])[:1])
|
||||||
}
|
}
|
||||||
|
@ -559,7 +559,7 @@ func localMonthsNameThai(t time.Time, abbr int) string {
|
||||||
return string(r[:1]) + "." + string(r[len(r)-2:len(r)-1]) + "."
|
return string(r[:1]) + "." + string(r[len(r)-2:len(r)-1]) + "."
|
||||||
}
|
}
|
||||||
if abbr == 4 {
|
if abbr == 4 {
|
||||||
return string([]rune(monthNamesThai[int(t.Month())-1]))
|
return monthNamesThai[int(t.Month())-1]
|
||||||
}
|
}
|
||||||
return string([]rune(monthNamesThai[int(t.Month())-1])[:1])
|
return string([]rune(monthNamesThai[int(t.Month())-1])[:1])
|
||||||
}
|
}
|
||||||
|
@ -575,7 +575,7 @@ func localMonthsNameTibetan(t time.Time, abbr int) string {
|
||||||
}
|
}
|
||||||
return "\u0f5f"
|
return "\u0f5f"
|
||||||
}
|
}
|
||||||
return string(monthNamesTibetan[int(t.Month())-1])
|
return monthNamesTibetan[int(t.Month())-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// localMonthsNameTurkish returns the Turkish name of the month.
|
// localMonthsNameTurkish returns the Turkish name of the month.
|
||||||
|
@ -661,7 +661,7 @@ func localMonthsNameXhosa(t time.Time, abbr int) string {
|
||||||
// localMonthsNameYi returns the Yi name of the month.
|
// localMonthsNameYi returns the Yi name of the month.
|
||||||
func localMonthsNameYi(t time.Time, abbr int) string {
|
func localMonthsNameYi(t time.Time, abbr int) string {
|
||||||
if abbr == 3 || abbr == 4 {
|
if abbr == 3 || abbr == 4 {
|
||||||
return string([]rune(monthNamesYi[int(t.Month())-1])) + "\ua1aa"
|
return string(monthNamesYi[int(t.Month())-1]) + "\ua1aa"
|
||||||
}
|
}
|
||||||
return string([]rune(monthNamesYi[int(t.Month())-1])[:1])
|
return string([]rune(monthNamesYi[int(t.Month())-1])[:1])
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// The optional parameter "autofit" specifies if make image size auto fits the
|
// The optional parameter "autofit" specifies if you make image size auto-fits the
|
||||||
// cell, the default value of that is 'false'.
|
// cell, the default value of that is 'false'.
|
||||||
//
|
//
|
||||||
// The optional parameter "hyperlink" specifies the hyperlink of the image.
|
// The optional parameter "hyperlink" specifies the hyperlink of the image.
|
||||||
|
@ -86,7 +86,7 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
|
||||||
// cells in this workbook. When the "hyperlink_type" is "Location",
|
// cells in this workbook. When the "hyperlink_type" is "Location",
|
||||||
// coordinates need to start with "#".
|
// coordinates need to start with "#".
|
||||||
//
|
//
|
||||||
// The optional parameter "positioning" defines two types of the position of a
|
// The optional parameter "positioning" defines two types of the position of an
|
||||||
// image in an Excel spreadsheet, "oneCell" (Move but don't size with
|
// image in an Excel spreadsheet, "oneCell" (Move but don't size with
|
||||||
// cells) or "absolute" (Don't move or size with cells). If you don't set this
|
// cells) or "absolute" (Don't move or size with cells). If you don't set this
|
||||||
// parameter, the default positioning is move and size with cells.
|
// parameter, the default positioning is move and size with cells.
|
||||||
|
|
|
@ -132,7 +132,7 @@ type PivotTableField struct {
|
||||||
//
|
//
|
||||||
func (f *File) AddPivotTable(opt *PivotTableOption) error {
|
func (f *File) AddPivotTable(opt *PivotTableOption) error {
|
||||||
// parameter validation
|
// parameter validation
|
||||||
dataSheet, pivotTableSheetPath, err := f.parseFormatPivotTableSet(opt)
|
_, pivotTableSheetPath, err := f.parseFormatPivotTableSet(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ func (f *File) AddPivotTable(opt *PivotTableOption) error {
|
||||||
sheetRelationshipsPivotTableXML := "../pivotTables/pivotTable" + strconv.Itoa(pivotTableID) + ".xml"
|
sheetRelationshipsPivotTableXML := "../pivotTables/pivotTable" + strconv.Itoa(pivotTableID) + ".xml"
|
||||||
pivotTableXML := strings.Replace(sheetRelationshipsPivotTableXML, "..", "xl", -1)
|
pivotTableXML := strings.Replace(sheetRelationshipsPivotTableXML, "..", "xl", -1)
|
||||||
pivotCacheXML := "xl/pivotCache/pivotCacheDefinition" + strconv.Itoa(pivotCacheID) + ".xml"
|
pivotCacheXML := "xl/pivotCache/pivotCacheDefinition" + strconv.Itoa(pivotCacheID) + ".xml"
|
||||||
err = f.addPivotCache(pivotCacheID, pivotCacheXML, opt, dataSheet)
|
err = f.addPivotCache(pivotCacheXML, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
|
||||||
// getPivotFieldsOrder provides a function to get order list of pivot table
|
// getPivotFieldsOrder provides a function to get order list of pivot table
|
||||||
// fields.
|
// fields.
|
||||||
func (f *File) getPivotFieldsOrder(opt *PivotTableOption) ([]string, error) {
|
func (f *File) getPivotFieldsOrder(opt *PivotTableOption) ([]string, error) {
|
||||||
order := []string{}
|
var order []string
|
||||||
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
|
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
|
||||||
if dataRange == "" {
|
if dataRange == "" {
|
||||||
dataRange = opt.DataRange
|
dataRange = opt.DataRange
|
||||||
|
@ -251,7 +251,7 @@ func (f *File) getPivotFieldsOrder(opt *PivotTableOption) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// addPivotCache provides a function to create a pivot cache by given properties.
|
// addPivotCache provides a function to create a pivot cache by given properties.
|
||||||
func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotTableOption, ws *xlsxWorksheet) error {
|
func (f *File) addPivotCache(pivotCacheXML string, opt *PivotTableOption) error {
|
||||||
// validate data range
|
// validate data range
|
||||||
definedNameRef := true
|
definedNameRef := true
|
||||||
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
|
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
|
||||||
|
@ -626,7 +626,7 @@ func (f *File) countPivotCache() int {
|
||||||
// getPivotFieldsIndex convert the column of the first row in the data region
|
// getPivotFieldsIndex convert the column of the first row in the data region
|
||||||
// to a sequential index by given fields and pivot option.
|
// to a sequential index by given fields and pivot option.
|
||||||
func (f *File) getPivotFieldsIndex(fields []PivotTableField, opt *PivotTableOption) ([]int, error) {
|
func (f *File) getPivotFieldsIndex(fields []PivotTableField, opt *PivotTableOption) ([]int, error) {
|
||||||
pivotFieldsIndex := []int{}
|
var pivotFieldsIndex []int
|
||||||
orders, err := f.getPivotFieldsOrder(opt)
|
orders, err := f.getPivotFieldsOrder(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pivotFieldsIndex, err
|
return pivotFieldsIndex, err
|
||||||
|
|
|
@ -235,15 +235,15 @@ func TestAddPivotTable(t *testing.T) {
|
||||||
_, err = f.getPivotFieldsOrder(&PivotTableOption{})
|
_, err = f.getPivotFieldsOrder(&PivotTableOption{})
|
||||||
assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
|
assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
|
||||||
// Test add pivot cache with empty data range
|
// Test add pivot cache with empty data range
|
||||||
assert.EqualError(t, f.addPivotCache(0, "", &PivotTableOption{}, nil), "parameter 'DataRange' parsing error: parameter is required")
|
assert.EqualError(t, f.addPivotCache("", &PivotTableOption{}), "parameter 'DataRange' parsing error: parameter is required")
|
||||||
// Test add pivot cache with invalid data range
|
// Test add pivot cache with invalid data range
|
||||||
assert.EqualError(t, f.addPivotCache(0, "", &PivotTableOption{
|
assert.EqualError(t, f.addPivotCache("", &PivotTableOption{
|
||||||
DataRange: "$A$1:$E$31",
|
DataRange: "$A$1:$E$31",
|
||||||
PivotTableRange: "Sheet1!$U$34:$O$2",
|
PivotTableRange: "Sheet1!$U$34:$O$2",
|
||||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||||
Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
|
Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
|
||||||
Data: []PivotTableField{{Data: "Sales"}},
|
Data: []PivotTableField{{Data: "Sales"}},
|
||||||
}, nil), "parameter 'DataRange' parsing error: parameter is invalid")
|
}), "parameter 'DataRange' parsing error: parameter is invalid")
|
||||||
// Test add pivot table with empty options
|
// Test add pivot table with empty options
|
||||||
assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOption{}), "parameter 'PivotTableRange' parsing error: parameter is required")
|
assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOption{}), "parameter 'PivotTableRange' parsing error: parameter is required")
|
||||||
// Test add pivot table with invalid data range
|
// Test add pivot table with invalid data range
|
||||||
|
|
2
rows.go
2
rows.go
|
@ -179,7 +179,7 @@ type ErrSheetNotExist struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrSheetNotExist) Error() string {
|
func (err ErrSheetNotExist) Error() string {
|
||||||
return fmt.Sprintf("sheet %s is not exist", string(err.SheetName))
|
return fmt.Sprintf("sheet %s is not exist", err.SheetName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// rowXMLIterator defined runtime use field for the worksheet row SAX parser.
|
// rowXMLIterator defined runtime use field for the worksheet row SAX parser.
|
||||||
|
|
42
sheet.go
42
sheet.go
|
@ -36,7 +36,7 @@ import (
|
||||||
// NewSheet provides the function to create a new sheet by given a worksheet
|
// NewSheet provides the function to create a new sheet by given a worksheet
|
||||||
// name and returns the index of the sheets in the workbook
|
// name and returns the index of the sheets in the workbook
|
||||||
// (spreadsheet) after it appended. Note that the worksheet names are not
|
// (spreadsheet) after it appended. Note that the worksheet names are not
|
||||||
// case sensitive, when creating a new spreadsheet file, the default
|
// case-sensitive, when creating a new spreadsheet file, the default
|
||||||
// worksheet named `Sheet1` will be created.
|
// worksheet named `Sheet1` will be created.
|
||||||
func (f *File) NewSheet(name string) int {
|
func (f *File) NewSheet(name string) int {
|
||||||
// Check if the worksheet already exists
|
// Check if the worksheet already exists
|
||||||
|
@ -111,7 +111,7 @@ func (f *File) mergeExpandedCols(ws *xlsxWorksheet) {
|
||||||
sort.Slice(ws.Cols.Col, func(i, j int) bool {
|
sort.Slice(ws.Cols.Col, func(i, j int) bool {
|
||||||
return ws.Cols.Col[i].Min < ws.Cols.Col[j].Min
|
return ws.Cols.Col[i].Min < ws.Cols.Col[j].Min
|
||||||
})
|
})
|
||||||
columns := []xlsxCol{}
|
var columns []xlsxCol
|
||||||
for i, n := 0, len(ws.Cols.Col); i < n; {
|
for i, n := 0, len(ws.Cols.Col); i < n; {
|
||||||
left := i
|
left := i
|
||||||
for i++; i < n && reflect.DeepEqual(
|
for i++; i < n && reflect.DeepEqual(
|
||||||
|
@ -219,10 +219,10 @@ func (f *File) setSheet(index int, name string) {
|
||||||
SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
|
SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
path := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
|
sheetXMLPath := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
|
||||||
f.sheetMap[trimSheetName(name)] = path
|
f.sheetMap[trimSheetName(name)] = sheetXMLPath
|
||||||
f.Sheet.Store(path, &ws)
|
f.Sheet.Store(sheetXMLPath, &ws)
|
||||||
f.xmlAttr[path] = []xml.Attr{NameSpaceSpreadSheet}
|
f.xmlAttr[sheetXMLPath] = []xml.Attr{NameSpaceSpreadSheet}
|
||||||
}
|
}
|
||||||
|
|
||||||
// relsWriter provides a function to save relationships after
|
// relsWriter provides a function to save relationships after
|
||||||
|
@ -384,7 +384,7 @@ func (f *File) getSheetID(name string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSheetIndex provides a function to get a sheet index of the workbook by
|
// GetSheetIndex provides a function to get a sheet index of the workbook by
|
||||||
// the given sheet name, the sheet names are not case sensitive. If the given
|
// the given sheet name, the sheet names are not case-sensitive. If the given
|
||||||
// sheet name is invalid or sheet doesn't exist, it will return an integer
|
// sheet name is invalid or sheet doesn't exist, it will return an integer
|
||||||
// type value -1.
|
// type value -1.
|
||||||
func (f *File) GetSheetIndex(name string) int {
|
func (f *File) GetSheetIndex(name string) int {
|
||||||
|
@ -442,12 +442,12 @@ func (f *File) getSheetMap() map[string]string {
|
||||||
for _, v := range f.workbookReader().Sheets.Sheet {
|
for _, v := range f.workbookReader().Sheets.Sheet {
|
||||||
for _, rel := range f.relsReader(f.getWorkbookRelsPath()).Relationships {
|
for _, rel := range f.relsReader(f.getWorkbookRelsPath()).Relationships {
|
||||||
if rel.ID == v.ID {
|
if rel.ID == v.ID {
|
||||||
path := f.getWorksheetPath(rel.Target)
|
sheetXMLPath := f.getWorksheetPath(rel.Target)
|
||||||
if _, ok := f.Pkg.Load(path); ok {
|
if _, ok := f.Pkg.Load(sheetXMLPath); ok {
|
||||||
maps[v.Name] = path
|
maps[v.Name] = sheetXMLPath
|
||||||
}
|
}
|
||||||
if _, ok := f.tempFiles.Load(path); ok {
|
if _, ok := f.tempFiles.Load(sheetXMLPath); ok {
|
||||||
maps[v.Name] = path
|
maps[v.Name] = sheetXMLPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,8 +478,8 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSheet provides a function to delete worksheet in a workbook by given
|
// DeleteSheet provides a function to delete worksheet in a workbook by given
|
||||||
// worksheet name, the sheet names are not case sensitive.the sheet names are
|
// worksheet name, the sheet names are not case-sensitive. The sheet names are
|
||||||
// not case sensitive. Use this method with caution, which will affect
|
// not case-sensitive. Use this method with caution, which will affect
|
||||||
// changes in references such as formulas, charts, and so on. If there is any
|
// changes in references such as formulas, charts, and so on. If there is any
|
||||||
// referenced value of the deleted worksheet, it will cause a file error when
|
// referenced value of the deleted worksheet, it will cause a file error when
|
||||||
// you open it. This function will be invalid when only the one worksheet is
|
// you open it. This function will be invalid when only the one worksheet is
|
||||||
|
@ -601,14 +601,14 @@ func (f *File) copySheet(from, to int) error {
|
||||||
}
|
}
|
||||||
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
|
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
|
||||||
toSheetID := strconv.Itoa(f.getSheetID(f.GetSheetName(to)))
|
toSheetID := strconv.Itoa(f.getSheetID(f.GetSheetName(to)))
|
||||||
path := "xl/worksheets/sheet" + toSheetID + ".xml"
|
sheetXMLPath := "xl/worksheets/sheet" + toSheetID + ".xml"
|
||||||
if len(worksheet.SheetViews.SheetView) > 0 {
|
if len(worksheet.SheetViews.SheetView) > 0 {
|
||||||
worksheet.SheetViews.SheetView[0].TabSelected = false
|
worksheet.SheetViews.SheetView[0].TabSelected = false
|
||||||
}
|
}
|
||||||
worksheet.Drawing = nil
|
worksheet.Drawing = nil
|
||||||
worksheet.TableParts = nil
|
worksheet.TableParts = nil
|
||||||
worksheet.PageSetUp = nil
|
worksheet.PageSetUp = nil
|
||||||
f.Sheet.Store(path, worksheet)
|
f.Sheet.Store(sheetXMLPath, worksheet)
|
||||||
toRels := "xl/worksheets/_rels/sheet" + toSheetID + ".xml.rels"
|
toRels := "xl/worksheets/_rels/sheet" + toSheetID + ".xml.rels"
|
||||||
fromRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(f.getSheetID(fromSheet)) + ".xml.rels"
|
fromRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(f.getSheetID(fromSheet)) + ".xml.rels"
|
||||||
if rels, ok := f.Pkg.Load(fromRels); ok && rels != nil {
|
if rels, ok := f.Pkg.Load(fromRels); ok && rels != nil {
|
||||||
|
@ -616,7 +616,7 @@ func (f *File) copySheet(from, to int) error {
|
||||||
}
|
}
|
||||||
fromSheetXMLPath := f.sheetMap[trimSheetName(fromSheet)]
|
fromSheetXMLPath := f.sheetMap[trimSheetName(fromSheet)]
|
||||||
fromSheetAttr := f.xmlAttr[fromSheetXMLPath]
|
fromSheetAttr := f.xmlAttr[fromSheetXMLPath]
|
||||||
f.xmlAttr[path] = fromSheetAttr
|
f.xmlAttr[sheetXMLPath] = fromSheetAttr
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,7 +779,7 @@ func (f *File) SetPanes(sheet, panes string) error {
|
||||||
ws.SheetViews.SheetView[len(ws.SheetViews.SheetView)-1].Pane = nil
|
ws.SheetViews.SheetView[len(ws.SheetViews.SheetView)-1].Pane = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s := []*xlsxSelection{}
|
var s []*xlsxSelection
|
||||||
for _, p := range fs.Panes {
|
for _, p := range fs.Panes {
|
||||||
s = append(s, &xlsxSelection{
|
s = append(s, &xlsxSelection{
|
||||||
ActiveCell: p.ActiveCell,
|
ActiveCell: p.ActiveCell,
|
||||||
|
@ -1207,7 +1207,7 @@ type (
|
||||||
// FitToWidth specified the number of horizontal pages to fit on.
|
// FitToWidth specified the number of horizontal pages to fit on.
|
||||||
FitToWidth int
|
FitToWidth int
|
||||||
// PageLayoutScale defines the print scaling. This attribute is restricted
|
// PageLayoutScale defines the print scaling. This attribute is restricted
|
||||||
// to values ranging from 10 (10%) to 400 (400%). This setting is
|
// to value ranging from 10 (10%) to 400 (400%). This setting is
|
||||||
// overridden when fitToWidth and/or fitToHeight are in use.
|
// overridden when fitToWidth and/or fitToHeight are in use.
|
||||||
PageLayoutScale uint
|
PageLayoutScale uint
|
||||||
)
|
)
|
||||||
|
@ -1534,7 +1534,7 @@ func (f *File) SetDefinedName(definedName *DefinedName) error {
|
||||||
scope = f.GetSheetName(*dn.LocalSheetID)
|
scope = f.GetSheetName(*dn.LocalSheetID)
|
||||||
}
|
}
|
||||||
if scope == definedName.Scope && dn.Name == definedName.Name {
|
if scope == definedName.Scope && dn.Name == definedName.Name {
|
||||||
return ErrDefinedNameduplicate
|
return ErrDefinedNameDuplicate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wb.DefinedNames.DefinedName = append(wb.DefinedNames.DefinedName, d)
|
wb.DefinedNames.DefinedName = append(wb.DefinedNames.DefinedName, d)
|
||||||
|
@ -1616,7 +1616,7 @@ func (f *File) GroupSheets(sheets []string) error {
|
||||||
return ErrGroupSheets
|
return ErrGroupSheets
|
||||||
}
|
}
|
||||||
// check worksheet exists
|
// check worksheet exists
|
||||||
wss := []*xlsxWorksheet{}
|
var wss []*xlsxWorksheet
|
||||||
for _, sheet := range sheets {
|
for _, sheet := range sheets {
|
||||||
worksheet, err := f.workSheetReader(sheet)
|
worksheet, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -276,7 +276,7 @@ func TestDefinedName(t *testing.T) {
|
||||||
Name: "Amount",
|
Name: "Amount",
|
||||||
RefersTo: "Sheet1!$A$2:$D$5",
|
RefersTo: "Sheet1!$A$2:$D$5",
|
||||||
Comment: "defined name comment",
|
Comment: "defined name comment",
|
||||||
}), ErrDefinedNameduplicate.Error())
|
}), ErrDefinedNameDuplicate.Error())
|
||||||
assert.EqualError(t, f.DeleteDefinedName(&DefinedName{
|
assert.EqualError(t, f.DeleteDefinedName(&DefinedName{
|
||||||
Name: "No Exist Defined Name",
|
Name: "No Exist Defined Name",
|
||||||
}), ErrDefinedNameScope.Error())
|
}), ErrDefinedNameScope.Error())
|
||||||
|
|
|
@ -135,7 +135,7 @@ func (o *View) getSheetViewOption(view *xlsxSheetView) {
|
||||||
*o = View(view.View)
|
*o = View(view.View)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
*o = View("normal")
|
*o = "normal"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
|
func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
|
||||||
|
@ -143,7 +143,7 @@ func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
|
func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
|
||||||
*o = TopLeftCell(string(view.TopLeftCell))
|
*o = TopLeftCell(view.TopLeftCell)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ZoomScale) setSheetViewOption(view *xlsxSheetView) {
|
func (o ZoomScale) setSheetViewOption(view *xlsxSheetView) {
|
||||||
|
|
|
@ -362,7 +362,7 @@ func (f *File) addSparklineGroupByStyle(ID int) *xlsxX14SparklineGroup {
|
||||||
// given formatting options. Sparklines are small charts that fit in a single
|
// given formatting options. Sparklines are small charts that fit in a single
|
||||||
// cell and are used to show trends in data. Sparklines are a feature of Excel
|
// cell and are used to show trends in data. Sparklines are a feature of Excel
|
||||||
// 2010 and later only. You can write them to an XLSX file that can be read by
|
// 2010 and later only. You can write them to an XLSX file that can be read by
|
||||||
// Excel 2007 but they won't be displayed. For example, add a grouped
|
// Excel 2007, but they won't be displayed. For example, add a grouped
|
||||||
// sparkline. Changes are applied to all three:
|
// sparkline. Changes are applied to all three:
|
||||||
//
|
//
|
||||||
// err := f.AddSparkline("Sheet1", &excelize.SparklineOption{
|
// err := f.AddSparkline("Sheet1", &excelize.SparklineOption{
|
||||||
|
|
|
@ -136,7 +136,7 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
|
||||||
// Note that the table must be at least two lines including the header. The
|
// Note that the table must be at least two lines including the header. The
|
||||||
// header cells must contain strings and must be unique.
|
// header cells must contain strings and must be unique.
|
||||||
//
|
//
|
||||||
// Currently only one table is allowed for a StreamWriter. AddTable must be
|
// Currently, only one table is allowed for a StreamWriter. AddTable must be
|
||||||
// called after the rows are written but before Flush.
|
// called after the rows are written but before Flush.
|
||||||
//
|
//
|
||||||
// See File.AddTable for details on the table format.
|
// See File.AddTable for details on the table format.
|
||||||
|
|
|
@ -223,7 +223,7 @@ func TestSetCellValFunc(t *testing.T) {
|
||||||
assert.NoError(t, sw.setCellValFunc(c, uint32(4294967295)))
|
assert.NoError(t, sw.setCellValFunc(c, uint32(4294967295)))
|
||||||
assert.NoError(t, sw.setCellValFunc(c, uint64(18446744073709551615)))
|
assert.NoError(t, sw.setCellValFunc(c, uint64(18446744073709551615)))
|
||||||
assert.NoError(t, sw.setCellValFunc(c, float32(100.1588)))
|
assert.NoError(t, sw.setCellValFunc(c, float32(100.1588)))
|
||||||
assert.NoError(t, sw.setCellValFunc(c, float64(100.1588)))
|
assert.NoError(t, sw.setCellValFunc(c, 100.1588))
|
||||||
assert.NoError(t, sw.setCellValFunc(c, " Hello"))
|
assert.NoError(t, sw.setCellValFunc(c, " Hello"))
|
||||||
assert.NoError(t, sw.setCellValFunc(c, []byte(" Hello")))
|
assert.NoError(t, sw.setCellValFunc(c, []byte(" Hello")))
|
||||||
assert.NoError(t, sw.setCellValFunc(c, time.Now().UTC()))
|
assert.NoError(t, sw.setCellValFunc(c, time.Now().UTC()))
|
||||||
|
|
|
@ -2465,7 +2465,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
cellData, col, row, err := f.prepareCell(ws, axis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -2851,7 +2851,7 @@ func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfRule := []*xlsxCfRule{}
|
var cfRule []*xlsxCfRule
|
||||||
for p, v := range format {
|
for p, v := range format {
|
||||||
var vt, ct string
|
var vt, ct string
|
||||||
var ok bool
|
var ok bool
|
||||||
|
@ -3052,7 +3052,7 @@ func ThemeColor(baseColor string, tint float64) string {
|
||||||
h, s, l = RGBToHSL(uint8(r), uint8(g), uint8(b))
|
h, s, l = RGBToHSL(uint8(r), uint8(g), uint8(b))
|
||||||
}
|
}
|
||||||
if tint < 0 {
|
if tint < 0 {
|
||||||
l *= (1 + tint)
|
l *= 1 + tint
|
||||||
} else {
|
} else {
|
||||||
l = l*(1-tint) + (1 - (1 - tint))
|
l = l*(1-tint) + (1 - (1 - tint))
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,10 +212,10 @@ func TestNewStyle(t *testing.T) {
|
||||||
assert.EqualError(t, err, ErrFontSize.Error())
|
assert.EqualError(t, err, ErrFontSize.Error())
|
||||||
|
|
||||||
// new numeric custom style
|
// new numeric custom style
|
||||||
fmt := "####;####"
|
numFmt := "####;####"
|
||||||
f.Styles.NumFmts = nil
|
f.Styles.NumFmts = nil
|
||||||
styleID, err = f.NewStyle(&Style{
|
styleID, err = f.NewStyle(&Style{
|
||||||
CustomNumFmt: &fmt,
|
CustomNumFmt: &numFmt,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 2, styleID)
|
assert.Equal(t, 2, styleID)
|
||||||
|
|
8
table.go
8
table.go
|
@ -383,7 +383,7 @@ func (f *File) writeAutoFilter(filter *xlsxAutoFilter, exp []int, tokens []strin
|
||||||
filter.FilterColumn[0].Filters = &xlsxFilters{Filter: filters}
|
filter.FilterColumn[0].Filters = &xlsxFilters{Filter: filters}
|
||||||
} else if len(exp) == 3 && exp[0] == 2 && exp[1] == 1 && exp[2] == 2 {
|
} else if len(exp) == 3 && exp[0] == 2 && exp[1] == 1 && exp[2] == 2 {
|
||||||
// Double equality with "or" operator.
|
// Double equality with "or" operator.
|
||||||
filters := []*xlsxFilter{}
|
var filters []*xlsxFilter
|
||||||
for _, v := range tokens {
|
for _, v := range tokens {
|
||||||
filters = append(filters, &xlsxFilter{Val: v})
|
filters = append(filters, &xlsxFilter{Val: v})
|
||||||
}
|
}
|
||||||
|
@ -419,7 +419,7 @@ func (f *File) writeCustomFilter(filter *xlsxAutoFilter, operator int, val strin
|
||||||
if filter.FilterColumn[0].CustomFilters != nil {
|
if filter.FilterColumn[0].CustomFilters != nil {
|
||||||
filter.FilterColumn[0].CustomFilters.CustomFilter = append(filter.FilterColumn[0].CustomFilters.CustomFilter, &customFilter)
|
filter.FilterColumn[0].CustomFilters.CustomFilter = append(filter.FilterColumn[0].CustomFilters.CustomFilter, &customFilter)
|
||||||
} else {
|
} else {
|
||||||
customFilters := []*xlsxCustomFilter{}
|
var customFilters []*xlsxCustomFilter
|
||||||
customFilters = append(customFilters, &customFilter)
|
customFilters = append(customFilters, &customFilter)
|
||||||
filter.FilterColumn[0].CustomFilters = &xlsxCustomFilters{CustomFilter: customFilters}
|
filter.FilterColumn[0].CustomFilters = &xlsxCustomFilters{CustomFilter: customFilters}
|
||||||
}
|
}
|
||||||
|
@ -435,8 +435,8 @@ func (f *File) writeCustomFilter(filter *xlsxAutoFilter, operator int, val strin
|
||||||
// ('x', '>', 2000, 'and', 'x', '<', 5000) -> exp1 and exp2
|
// ('x', '>', 2000, 'and', 'x', '<', 5000) -> exp1 and exp2
|
||||||
//
|
//
|
||||||
func (f *File) parseFilterExpression(expression string, tokens []string) ([]int, []string, error) {
|
func (f *File) parseFilterExpression(expression string, tokens []string) ([]int, []string, error) {
|
||||||
expressions := []int{}
|
var expressions []int
|
||||||
t := []string{}
|
var t []string
|
||||||
if len(tokens) == 7 {
|
if len(tokens) == 7 {
|
||||||
// The number of tokens will be either 3 (for 1 expression) or 7 (for 2
|
// The number of tokens will be either 3 (for 1 expression) or 7 (for 2
|
||||||
// expressions).
|
// expressions).
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
import "encoding/xml"
|
|
||||||
|
|
||||||
// XMLHeaderByte define an XML declaration can also contain a standalone
|
|
||||||
// declaration.
|
|
||||||
var XMLHeaderByte = []byte(xml.Header)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultXMLPathContentTypes = "[Content_Types].xml"
|
defaultXMLPathContentTypes = "[Content_Types].xml"
|
||||||
defaultXMLPathDocPropsApp = "docProps/app.xml"
|
defaultXMLPathDocPropsApp = "docProps/app.xml"
|
||||||
|
|
|
@ -66,13 +66,13 @@ type xlsxCalcChain struct {
|
||||||
// | same dependency level. Child chains are series of
|
// | same dependency level. Child chains are series of
|
||||||
// | calculations that can be independently farmed out to
|
// | calculations that can be independently farmed out to
|
||||||
// | other threads or processors.The possible values for
|
// | other threads or processors.The possible values for
|
||||||
// | this attribute are defined by the W3C XML Schema
|
// | this attribute is defined by the W3C XML Schema
|
||||||
// | boolean datatype.
|
// | boolean datatype.
|
||||||
// |
|
// |
|
||||||
// t (New Thread) | A Boolean flag indicating whether the cell's formula
|
// t (New Thread) | A Boolean flag indicating whether the cell's formula
|
||||||
// | starts a new thread. True if the cell's formula starts
|
// | starts a new thread. True if the cell's formula starts
|
||||||
// | a new thread, false otherwise.The possible values for
|
// | a new thread, false otherwise.The possible values for
|
||||||
// | this attribute are defined by the W3C XML Schema
|
// | this attribute is defined by the W3C XML Schema
|
||||||
// | boolean datatype.
|
// | boolean datatype.
|
||||||
//
|
//
|
||||||
type xlsxCalcChainC struct {
|
type xlsxCalcChainC struct {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// xlsxTypes directly maps the types element of content types for relationship
|
// xlsxTypes directly maps the types' element of content types for relationship
|
||||||
// parts, it takes a Multipurpose Internet Mail Extension (MIME) media type as a
|
// parts, it takes a Multipurpose Internet Mail Extension (MIME) media type as a
|
||||||
// value.
|
// value.
|
||||||
type xlsxTypes struct {
|
type xlsxTypes struct {
|
||||||
|
|
|
@ -197,7 +197,7 @@ type xlsxCellStyle struct {
|
||||||
// contains the master formatting records (xf's) which define the formatting for
|
// contains the master formatting records (xf's) which define the formatting for
|
||||||
// all named cell styles in this workbook. Master formatting records reference
|
// all named cell styles in this workbook. Master formatting records reference
|
||||||
// individual elements of formatting (e.g., number format, font definitions,
|
// individual elements of formatting (e.g., number format, font definitions,
|
||||||
// cell fills, etc) by specifying a zero-based index into those collections.
|
// cell fills, etc.) by specifying a zero-based index into those collections.
|
||||||
// Master formatting records also specify whether to apply or ignore particular
|
// Master formatting records also specify whether to apply or ignore particular
|
||||||
// aspects of formatting.
|
// aspects of formatting.
|
||||||
type xlsxCellStyleXfs struct {
|
type xlsxCellStyleXfs struct {
|
||||||
|
|
|
@ -14,7 +14,7 @@ package excelize
|
||||||
import "encoding/xml"
|
import "encoding/xml"
|
||||||
|
|
||||||
// xlsxTable directly maps the table element. A table helps organize and provide
|
// xlsxTable directly maps the table element. A table helps organize and provide
|
||||||
// structure to lists of information in a worksheet. Tables have clearly labeled
|
// structure to list of information in a worksheet. Tables have clearly labeled
|
||||||
// columns, rows, and data regions. Tables make it easier for users to sort,
|
// columns, rows, and data regions. Tables make it easier for users to sort,
|
||||||
// analyze, format, manage, add, and delete information. This element is the
|
// analyze, format, manage, add, and delete information. This element is the
|
||||||
// root element for a table that is not a single cell XML table.
|
// root element for a table that is not a single cell XML table.
|
||||||
|
|
Loading…
Reference in New Issue