Format code, update documentation and remove exported variable `XMLHeaderByte`

This commit is contained in:
xuri 2022-03-24 00:19:30 +08:00
parent 139ee4c4b0
commit 8a335225c7
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
36 changed files with 330 additions and 328 deletions

364
calc.go

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -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 := "", ""

View File

@ -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),
})) }))

View File

@ -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

View File

@ -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
View File

@ -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:
// //

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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]...))

View File

@ -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)},

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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.

View File

@ -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")

View File

@ -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])
} }

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 {

View File

@ -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())

View File

@ -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) {

View File

@ -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{

View File

@ -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.

View File

@ -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()))

View File

@ -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))
} }

View File

@ -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)

View File

@ -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).

View File

@ -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"

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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.