2022-01-09 00:20:42 +08:00
|
|
|
// Copyright 2016 - 2022 The excelize Authors. All rights reserved. Use of
|
2018-09-14 00:44:23 +08:00
|
|
|
// this source code is governed by a BSD-style license that can be found in
|
|
|
|
// the LICENSE file.
|
|
|
|
//
|
|
|
|
// Package excelize providing a set of functions that allow you to write to
|
2020-06-22 00:14:56 +08:00
|
|
|
// and read from XLSX / XLSM / XLTM files. Supports reading and writing
|
2021-03-30 23:02:22 +08:00
|
|
|
// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
|
2020-06-22 00:14:56 +08:00
|
|
|
// complex components by high compatibility, and provided streaming API for
|
|
|
|
// generating or reading data from a worksheet with huge amounts of data. This
|
2021-04-04 15:29:43 +08:00
|
|
|
// library needs Go version 1.15 or later.
|
2018-09-14 00:58:48 +08:00
|
|
|
|
2016-08-30 21:54:28 +08:00
|
|
|
package excelize
|
|
|
|
|
|
|
|
import (
|
2017-07-24 10:26:02 +08:00
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
2021-12-27 23:34:14 +08:00
|
|
|
"os"
|
2018-03-12 20:14:39 +08:00
|
|
|
"reflect"
|
2016-08-30 21:54:28 +08:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2017-07-24 10:26:02 +08:00
|
|
|
"time"
|
2016-08-30 21:54:28 +08:00
|
|
|
)
|
|
|
|
|
2021-09-09 23:43:16 +08:00
|
|
|
// CellType is the type of cell value type.
|
|
|
|
type CellType byte
|
|
|
|
|
|
|
|
// Cell value types enumeration.
|
|
|
|
const (
|
|
|
|
CellTypeUnset CellType = iota
|
|
|
|
CellTypeBool
|
|
|
|
CellTypeDate
|
|
|
|
CellTypeError
|
|
|
|
CellTypeNumber
|
|
|
|
CellTypeString
|
|
|
|
)
|
|
|
|
|
2018-05-26 16:23:15 +08:00
|
|
|
const (
|
|
|
|
// STCellFormulaTypeArray defined the formula is an array formula.
|
|
|
|
STCellFormulaTypeArray = "array"
|
|
|
|
// STCellFormulaTypeDataTable defined the formula is a data table formula.
|
|
|
|
STCellFormulaTypeDataTable = "dataTable"
|
|
|
|
// STCellFormulaTypeNormal defined the formula is a regular cell formula.
|
|
|
|
STCellFormulaTypeNormal = "normal"
|
|
|
|
// STCellFormulaTypeShared defined the formula is part of a shared formula.
|
|
|
|
STCellFormulaTypeShared = "shared"
|
|
|
|
)
|
|
|
|
|
2021-09-09 23:43:16 +08:00
|
|
|
// cellTypes mapping the cell's data type and enumeration.
|
|
|
|
var cellTypes = map[string]CellType{
|
|
|
|
"b": CellTypeBool,
|
|
|
|
"d": CellTypeDate,
|
|
|
|
"n": CellTypeNumber,
|
|
|
|
"e": CellTypeError,
|
|
|
|
"s": CellTypeString,
|
|
|
|
"str": CellTypeString,
|
|
|
|
"inlineStr": CellTypeString,
|
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// GetCellValue provides a function to get formatted value from cell by given
|
This closes #787, avoid duplicate rich text string items, new formula fn: BIN2DEC, BIN2HEX, BIN2OCT, HEX2BIN, HEX2DEC, HEX2OCT, OCT2BIN, OCT2DEC, OCT2HEX
2021-02-21 00:21:45 +08:00
|
|
|
// worksheet name and axis in spreadsheet file. If it is possible to apply a
|
|
|
|
// format to the cell value, it will do so, if not then an error will be
|
2021-08-12 00:02:27 +08:00
|
|
|
// returned, along with the raw value of the cell. All cells' values will be
|
|
|
|
// the same in a merged range.
|
2021-09-05 11:59:50 +08:00
|
|
|
func (f *File) GetCellValue(sheet, axis string, opts ...Options) (string, error) {
|
2019-03-23 20:08:06 +08:00
|
|
|
return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
|
2021-09-05 11:59:50 +08:00
|
|
|
val, err := c.getValueFrom(f, f.sharedStringsReader(), parseOptions(opts...).RawCellValue)
|
2019-03-23 20:08:06 +08:00
|
|
|
return val, true, err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
})
|
2017-05-24 14:17:35 +08:00
|
|
|
}
|
|
|
|
|
2021-09-09 23:43:16 +08:00
|
|
|
// GetCellType provides a function to get the cell's data type by given
|
|
|
|
// worksheet name and axis in spreadsheet file.
|
|
|
|
func (f *File) GetCellType(sheet, axis string) (CellType, error) {
|
|
|
|
var (
|
|
|
|
err error
|
|
|
|
cellTypeStr string
|
2021-09-17 00:15:51 +08:00
|
|
|
cellType CellType
|
2021-09-09 23:43:16 +08:00
|
|
|
)
|
|
|
|
if cellTypeStr, err = f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
|
|
|
|
return c.T, true, nil
|
|
|
|
}); err != nil {
|
|
|
|
return CellTypeUnset, err
|
|
|
|
}
|
|
|
|
cellType = cellTypes[cellTypeStr]
|
|
|
|
return cellType, err
|
|
|
|
}
|
|
|
|
|
This closes #787, avoid duplicate rich text string items, new formula fn: BIN2DEC, BIN2HEX, BIN2OCT, HEX2BIN, HEX2DEC, HEX2OCT, OCT2BIN, OCT2DEC, OCT2HEX
2021-02-21 00:21:45 +08:00
|
|
|
// SetCellValue provides a function to set the value of a cell. The specified
|
2021-02-19 00:03:51 +08:00
|
|
|
// coordinates should not be in the first row of the table, a complex number
|
|
|
|
// can be set with string text. The following shows the supported data
|
|
|
|
// types:
|
2017-07-24 10:26:02 +08:00
|
|
|
//
|
|
|
|
// int
|
|
|
|
// int8
|
|
|
|
// int16
|
|
|
|
// int32
|
|
|
|
// int64
|
2017-10-18 18:42:20 +08:00
|
|
|
// uint
|
|
|
|
// uint8
|
|
|
|
// uint16
|
|
|
|
// uint32
|
|
|
|
// uint64
|
2017-07-24 10:26:02 +08:00
|
|
|
// float32
|
|
|
|
// float64
|
|
|
|
// string
|
|
|
|
// []byte
|
2018-01-05 09:39:31 +08:00
|
|
|
// time.Duration
|
2017-07-24 10:26:02 +08:00
|
|
|
// time.Time
|
2018-01-26 01:06:40 +08:00
|
|
|
// bool
|
2017-07-24 10:26:02 +08:00
|
|
|
// nil
|
|
|
|
//
|
|
|
|
// Note that default date format is m/d/yy h:mm of time.Time type value. You can
|
|
|
|
// set numbers format by SetCellStyle() method.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetCellValue(sheet, axis string, value interface{}) error {
|
2019-04-16 10:57:21 +08:00
|
|
|
var err error
|
|
|
|
switch v := value.(type) {
|
|
|
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
|
|
|
err = f.setCellIntFunc(sheet, axis, v)
|
|
|
|
case float32:
|
|
|
|
err = f.SetCellFloat(sheet, axis, float64(v), -1, 32)
|
|
|
|
case float64:
|
|
|
|
err = f.SetCellFloat(sheet, axis, v, -1, 64)
|
|
|
|
case string:
|
|
|
|
err = f.SetCellStr(sheet, axis, v)
|
|
|
|
case []byte:
|
|
|
|
err = f.SetCellStr(sheet, axis, string(v))
|
|
|
|
case time.Duration:
|
2019-12-29 12:45:10 +08:00
|
|
|
_, d := setCellDuration(v)
|
|
|
|
err = f.SetCellDefault(sheet, axis, d)
|
2019-04-16 10:57:21 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = f.setDefaultTimeStyle(sheet, axis, 21)
|
|
|
|
case time.Time:
|
|
|
|
err = f.setCellTimeFunc(sheet, axis, v)
|
|
|
|
case bool:
|
|
|
|
err = f.SetCellBool(sheet, axis, v)
|
|
|
|
case nil:
|
2021-02-19 00:03:51 +08:00
|
|
|
err = f.SetCellDefault(sheet, axis, "")
|
2019-04-16 10:57:21 +08:00
|
|
|
default:
|
2019-08-13 21:39:12 +08:00
|
|
|
err = f.SetCellStr(sheet, axis, fmt.Sprint(value))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-08-13 01:32:44 +08:00
|
|
|
// String extracts characters from a string item.
|
|
|
|
func (x xlsxSI) String() string {
|
|
|
|
if len(x.R) > 0 {
|
|
|
|
var rows strings.Builder
|
|
|
|
for _, s := range x.R {
|
|
|
|
if s.T != nil {
|
|
|
|
rows.WriteString(s.T.Val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bstrUnmarshal(rows.String())
|
|
|
|
}
|
|
|
|
if x.T != nil {
|
|
|
|
return bstrUnmarshal(x.T.Val)
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// hasValue determine if cell non-blank value.
|
|
|
|
func (c *xlsxC) hasValue() bool {
|
|
|
|
return c.S != 0 || c.V != "" || c.F != nil || c.T != ""
|
|
|
|
}
|
|
|
|
|
2019-04-16 10:57:21 +08:00
|
|
|
// setCellIntFunc is a wrapper of SetCellInt.
|
|
|
|
func (f *File) setCellIntFunc(sheet, axis string, value interface{}) error {
|
2019-04-15 11:22:57 +08:00
|
|
|
var err error
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
switch v := value.(type) {
|
2017-07-24 10:26:02 +08:00
|
|
|
case int:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, v)
|
2017-07-24 10:26:02 +08:00
|
|
|
case int8:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-07-24 10:26:02 +08:00
|
|
|
case int16:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-07-24 10:26:02 +08:00
|
|
|
case int32:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-07-24 10:26:02 +08:00
|
|
|
case int64:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-10-18 18:42:20 +08:00
|
|
|
case uint:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-10-18 18:42:20 +08:00
|
|
|
case uint8:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-10-18 18:42:20 +08:00
|
|
|
case uint16:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-10-18 18:42:20 +08:00
|
|
|
case uint32:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2017-10-18 18:42:20 +08:00
|
|
|
case uint64:
|
2019-04-15 11:22:57 +08:00
|
|
|
err = f.SetCellInt(sheet, axis, int(v))
|
2019-04-16 10:57:21 +08:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// setCellTimeFunc provides a method to process time type of value for
|
|
|
|
// SetCellValue.
|
|
|
|
func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-16 10:57:21 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
2019-12-29 12:45:10 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-07 00:57:43 +08:00
|
|
|
ws.Lock()
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
2021-07-07 00:57:43 +08:00
|
|
|
ws.Unlock()
|
2019-12-29 12:45:10 +08:00
|
|
|
|
|
|
|
var isNum bool
|
|
|
|
cellData.T, cellData.V, isNum, err = setCellTime(value)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if isNum {
|
2019-04-16 10:57:21 +08:00
|
|
|
err = f.setDefaultTimeStyle(sheet, axis, 22)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
2019-04-15 11:22:57 +08:00
|
|
|
return err
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
2021-07-07 00:57:43 +08:00
|
|
|
// setCellTime prepares cell type and Excel time by given Go time.Time type
|
|
|
|
// timestamp.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellTime(value time.Time) (t string, b string, isNum bool, err error) {
|
|
|
|
var excelTime float64
|
2021-11-24 00:09:35 +08:00
|
|
|
_, offset := value.In(value.Location()).Zone()
|
|
|
|
value = value.Add(time.Duration(offset) * time.Second)
|
2021-12-31 00:00:01 +08:00
|
|
|
if excelTime, err = timeToExcelTime(value); err != nil {
|
2019-12-29 12:45:10 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
isNum = excelTime > 0
|
|
|
|
if isNum {
|
|
|
|
t, b = setCellDefault(strconv.FormatFloat(excelTime, 'f', -1, 64))
|
|
|
|
} else {
|
|
|
|
t, b = setCellDefault(value.Format(time.RFC3339Nano))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-07-07 00:57:43 +08:00
|
|
|
// setCellDuration prepares cell type and value by given Go time.Duration type
|
|
|
|
// time duration.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellDuration(value time.Duration) (t string, v string) {
|
|
|
|
v = strconv.FormatFloat(value.Seconds()/86400.0, 'f', -1, 32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// SetCellInt provides a function to set int type value of a cell by given
|
2018-01-26 01:06:40 +08:00
|
|
|
// worksheet name, cell coordinates and cell value.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetCellInt(sheet, axis string, value int) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-05 00:03:56 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
2019-12-29 12:45:10 +08:00
|
|
|
cellData.T, cellData.V = setCellInt(value)
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2018-01-26 01:06:40 +08:00
|
|
|
|
2021-07-07 00:57:43 +08:00
|
|
|
// setCellInt prepares cell type and string type cell value by a given
|
|
|
|
// integer.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellInt(value int) (t string, v string) {
|
|
|
|
v = strconv.Itoa(value)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// SetCellBool provides a function to set bool type value of a cell by given
|
|
|
|
// worksheet name, cell name and cell value.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetCellBool(sheet, axis string, value bool) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-07 00:57:43 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
2019-12-29 12:45:10 +08:00
|
|
|
cellData.T, cellData.V = setCellBool(value)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-07-07 00:57:43 +08:00
|
|
|
// setCellBool prepares cell type and string type cell value by a given
|
|
|
|
// boolean value.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellBool(value bool) (t string, v string) {
|
|
|
|
t = "b"
|
2018-01-26 01:06:40 +08:00
|
|
|
if value {
|
2019-12-29 12:45:10 +08:00
|
|
|
v = "1"
|
2018-01-26 01:06:40 +08:00
|
|
|
} else {
|
2019-12-29 12:45:10 +08:00
|
|
|
v = "0"
|
2018-01-26 01:06:40 +08:00
|
|
|
}
|
2019-12-29 12:45:10 +08:00
|
|
|
return
|
2018-01-26 01:06:40 +08:00
|
|
|
}
|
|
|
|
|
2019-03-21 11:41:46 +08:00
|
|
|
// SetCellFloat sets a floating point value into a cell. The prec parameter
|
2019-03-21 14:09:25 +08:00
|
|
|
// 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
|
|
|
|
// represent the number. bitSize is 32 or 64 depending on if a float32 or
|
|
|
|
// float64 was originally used for the value. For Example:
|
|
|
|
//
|
|
|
|
// var x float32 = 1.325
|
|
|
|
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-07 00:57:43 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
2019-12-29 12:45:10 +08:00
|
|
|
cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2019-03-21 11:41:46 +08:00
|
|
|
}
|
|
|
|
|
2021-07-07 00:57:43 +08:00
|
|
|
// setCellFloat prepares cell type and string type cell value by a given
|
|
|
|
// float value.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellFloat(value float64, prec, bitSize int) (t string, v string) {
|
|
|
|
v = strconv.FormatFloat(value, 'f', prec, bitSize)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// SetCellStr provides a function to set string type value of a cell. Total
|
|
|
|
// number of characters that a cell can contain 32767 characters.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetCellStr(sheet, axis, value string) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-05 00:03:56 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
2021-12-27 23:34:14 +08:00
|
|
|
cellData.T, cellData.V, err = f.setCellString(value)
|
2019-12-29 12:45:10 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-05-26 02:09:39 +08:00
|
|
|
// setCellString provides a function to set string type to shared string
|
|
|
|
// table.
|
2021-12-27 23:34:14 +08:00
|
|
|
func (f *File) setCellString(value string) (t, v string, err error) {
|
2020-05-29 00:26:40 +08:00
|
|
|
if len(value) > TotalCellChars {
|
2021-11-17 00:25:36 +08:00
|
|
|
value = value[:TotalCellChars]
|
2020-05-26 02:09:39 +08:00
|
|
|
}
|
|
|
|
t = "s"
|
2021-12-27 23:34:14 +08:00
|
|
|
var si int
|
|
|
|
if si, err = f.setSharedString(value); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
v = strconv.Itoa(si)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// sharedStringsLoader load shared string table from system temporary file to
|
|
|
|
// memory, and reset shared string table for reader.
|
|
|
|
func (f *File) sharedStringsLoader() (err error) {
|
|
|
|
f.Lock()
|
|
|
|
defer f.Unlock()
|
2022-01-09 00:20:42 +08:00
|
|
|
if path, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok {
|
|
|
|
f.Pkg.Store(defaultXMLPathSharedStrings, f.readBytes(defaultXMLPathSharedStrings))
|
|
|
|
f.tempFiles.Delete(defaultXMLPathSharedStrings)
|
2022-01-11 00:24:24 +08:00
|
|
|
if err = os.Remove(path.(string)); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
f.SharedStrings = nil
|
|
|
|
}
|
|
|
|
if f.sharedStringTemp != nil {
|
|
|
|
if err := f.sharedStringTemp.Close(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
f.tempFiles.Delete(defaultTempFileSST)
|
|
|
|
f.sharedStringItem, err = nil, os.Remove(f.sharedStringTemp.Name())
|
|
|
|
f.sharedStringTemp = nil
|
2021-12-27 23:34:14 +08:00
|
|
|
}
|
2020-05-26 02:09:39 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// setSharedString provides a function to add string to the share string table.
|
2021-12-27 23:34:14 +08:00
|
|
|
func (f *File) setSharedString(val string) (int, error) {
|
|
|
|
if err := f.sharedStringsLoader(); err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
2020-05-26 02:09:39 +08:00
|
|
|
sst := f.sharedStringsReader()
|
2020-08-15 00:09:50 +08:00
|
|
|
f.Lock()
|
|
|
|
defer f.Unlock()
|
2020-05-27 00:02:29 +08:00
|
|
|
if i, ok := f.sharedStringsMap[val]; ok {
|
2021-12-27 23:34:14 +08:00
|
|
|
return i, nil
|
2020-05-26 02:09:39 +08:00
|
|
|
}
|
|
|
|
sst.Count++
|
|
|
|
sst.UniqueCount++
|
2020-07-01 22:41:29 +08:00
|
|
|
t := xlsxT{Val: val}
|
2021-07-31 14:20:29 +08:00
|
|
|
_, val, t.Space = setCellStr(val)
|
2020-07-01 22:41:29 +08:00
|
|
|
sst.SI = append(sst.SI, xlsxSI{T: &t})
|
2020-05-27 00:02:29 +08:00
|
|
|
f.sharedStringsMap[val] = sst.UniqueCount - 1
|
2021-12-27 23:34:14 +08:00
|
|
|
return sst.UniqueCount - 1, nil
|
2020-05-26 02:09:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// setCellStr provides a function to set string type to cell.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellStr(value string) (t string, v string, ns xml.Attr) {
|
2020-05-29 00:26:40 +08:00
|
|
|
if len(value) > TotalCellChars {
|
2021-11-17 00:25:36 +08:00
|
|
|
value = value[:TotalCellChars]
|
2019-04-14 12:55:44 +08:00
|
|
|
}
|
2021-07-31 14:20:29 +08:00
|
|
|
if len(value) > 0 {
|
|
|
|
prefix, suffix := value[0], value[len(value)-1]
|
2021-12-30 00:36:04 +08:00
|
|
|
for _, ascii := range []byte{9, 10, 13, 32} {
|
2021-07-31 14:20:29 +08:00
|
|
|
if prefix == ascii || suffix == ascii {
|
|
|
|
ns = xml.Attr{
|
|
|
|
Name: xml.Name{Space: NameSpaceXML, Local: "space"},
|
|
|
|
Value: "preserve",
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
2016-12-24 22:47:36 +08:00
|
|
|
}
|
|
|
|
}
|
2021-12-31 00:00:01 +08:00
|
|
|
t, v = "str", bstrMarshal(value)
|
2019-12-29 12:45:10 +08:00
|
|
|
return
|
2017-05-05 14:40:28 +08:00
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// SetCellDefault provides a function to set string type value of a cell as
|
|
|
|
// default format without escaping the cell.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetCellDefault(sheet, axis, value string) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-07-07 00:57:43 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
2019-12-29 12:45:10 +08:00
|
|
|
cellData.T, cellData.V = setCellDefault(value)
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
2021-07-07 00:57:43 +08:00
|
|
|
// setCellDefault prepares cell type and string type cell value by a given
|
|
|
|
// string.
|
2019-12-29 12:45:10 +08:00
|
|
|
func setCellDefault(value string) (t string, v string) {
|
|
|
|
v = value
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// GetCellFormula provides a function to get formula from cell by given
|
|
|
|
// worksheet name and axis in XLSX file.
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) GetCellFormula(sheet, axis string) (string, error) {
|
|
|
|
return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if c.F == nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return "", false, nil
|
2016-08-30 21:54:28 +08:00
|
|
|
}
|
2021-09-03 22:51:56 +08:00
|
|
|
if c.F.T == STCellFormulaTypeShared && c.F.Si != nil {
|
2022-01-09 00:20:42 +08:00
|
|
|
return getSharedFormula(x, *c.F.Si, c.R), true, nil
|
2018-05-26 16:23:15 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return c.F.Content, true, nil
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
})
|
2018-05-26 16:23:15 +08:00
|
|
|
}
|
|
|
|
|
2019-09-22 20:52:01 +08:00
|
|
|
// FormulaOpts can be passed to SetCellFormula to use other formula types.
|
|
|
|
type FormulaOpts struct {
|
|
|
|
Type *string // Formula type
|
|
|
|
Ref *string // Shared formula ref
|
|
|
|
}
|
|
|
|
|
2021-09-03 22:51:56 +08:00
|
|
|
// SetCellFormula provides a function to set formula on the cell is taken
|
|
|
|
// according to the given worksheet name (case sensitive) and cell formula
|
|
|
|
// settings. The result of the formula cell can be calculated when the
|
|
|
|
// worksheet is opened by the Office Excel application or can be using
|
|
|
|
// the "CalcCellValue" function also can get the calculated cell value. If
|
|
|
|
// the Excel application doesn't calculate the formula automatically when the
|
|
|
|
// workbook has been opened, please call "UpdateLinkedValue" after setting
|
|
|
|
// the cell formula functions.
|
|
|
|
//
|
|
|
|
// Example 1, set normal formula "=SUM(A1,B1)" for the cell "A3" on "Sheet1":
|
|
|
|
//
|
|
|
|
// err := f.SetCellFormula("Sheet1", "A3", "=SUM(A1,B1)")
|
|
|
|
//
|
|
|
|
// Example 2, set one-dimensional vertical constant array (row array) formula
|
|
|
|
// "1,2,3" for the cell "A3" on "Sheet1":
|
|
|
|
//
|
|
|
|
// err := f.SetCellFormula("Sheet1", "A3", "={1,2,3}")
|
|
|
|
//
|
|
|
|
// Example 3, set one-dimensional horizontal constant array (column array)
|
|
|
|
// formula '"a","b","c"' for the cell "A3" on "Sheet1":
|
|
|
|
//
|
|
|
|
// err := f.SetCellFormula("Sheet1", "A3", "={\"a\",\"b\",\"c\"}")
|
|
|
|
//
|
|
|
|
// Example 4, set two-dimensional constant array formula '{1,2,"a","b"}' for
|
|
|
|
// the cell "A3" on "Sheet1":
|
|
|
|
//
|
|
|
|
// formulaType, ref := excelize.STCellFormulaTypeArray, "A3:A3"
|
|
|
|
// err := f.SetCellFormula("Sheet1", "A3", "={1,2,\"a\",\"b\"}",
|
|
|
|
// excelize.FormulaOpts{Ref: &ref, Type: &formulaType})
|
|
|
|
//
|
|
|
|
// Example 5, set range array formula "A1:A2" for the cell "A3" on "Sheet1":
|
|
|
|
//
|
|
|
|
// formulaType, ref := excelize.STCellFormulaTypeArray, "A3:A3"
|
|
|
|
// err := f.SetCellFormula("Sheet1", "A3", "=A1:A2",
|
|
|
|
// excelize.FormulaOpts{Ref: &ref, Type: &formulaType})
|
|
|
|
//
|
|
|
|
// Example 6, set shared formula "=A1+B1" for the cell "C1:C5"
|
|
|
|
// on "Sheet1", "C1" is the master cell:
|
|
|
|
//
|
|
|
|
// formulaType, ref := excelize.STCellFormulaTypeShared, "C1:C5"
|
|
|
|
// err := f.SetCellFormula("Sheet1", "C1", "=A1+B1",
|
|
|
|
// excelize.FormulaOpts{Ref: &ref, Type: &formulaType})
|
|
|
|
//
|
2021-09-05 11:59:50 +08:00
|
|
|
// Example 7, set table formula "=SUM(Table1[[A]:[B]])" for the cell "C2"
|
|
|
|
// on "Sheet1":
|
|
|
|
//
|
|
|
|
// package main
|
|
|
|
//
|
|
|
|
// import (
|
|
|
|
// "fmt"
|
|
|
|
//
|
|
|
|
// "github.com/xuri/excelize/v2"
|
|
|
|
// )
|
|
|
|
//
|
|
|
|
// func main() {
|
|
|
|
// f := excelize.NewFile()
|
|
|
|
// for idx, row := range [][]interface{}{{"A", "B", "C"}, {1, 2}} {
|
|
|
|
// if err := f.SetSheetRow("Sheet1", fmt.Sprintf("A%d", idx+1), &row); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// if err := f.AddTable("Sheet1", "A1", "C2",
|
|
|
|
// `{"table_name":"Table1","table_style":"TableStyleMedium2"}`); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// formulaType := excelize.STCellFormulaTypeDataTable
|
|
|
|
// if err := f.SetCellFormula("Sheet1", "C2", "=SUM(Table1[[A]:[B]])",
|
|
|
|
// excelize.FormulaOpts{Type: &formulaType}); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// if err := f.SaveAs("Book1.xlsx"); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
2019-09-22 20:52:01 +08:00
|
|
|
func (f *File) SetCellFormula(sheet, axis, formula string, opts ...FormulaOpts) error {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
cellData, _, _, err := f.prepareCell(ws, sheet, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-02-22 22:17:38 +08:00
|
|
|
if formula == "" {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
cellData.F = nil
|
2020-04-23 02:01:14 +08:00
|
|
|
f.deleteCalcChain(f.getSheetID(sheet), axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2019-02-22 22:17:38 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
if cellData.F != nil {
|
|
|
|
cellData.F.Content = formula
|
2017-01-19 14:05:32 +08:00
|
|
|
} else {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
cellData.F = &xlsxF{Content: formula}
|
|
|
|
}
|
2019-09-22 20:52:01 +08:00
|
|
|
|
|
|
|
for _, o := range opts {
|
|
|
|
if o.Type != nil {
|
2021-09-05 11:59:50 +08:00
|
|
|
if *o.Type == STCellFormulaTypeDataTable {
|
|
|
|
return err
|
|
|
|
}
|
2019-09-22 20:52:01 +08:00
|
|
|
cellData.F.T = *o.Type
|
2021-09-03 22:51:56 +08:00
|
|
|
if cellData.F.T == STCellFormulaTypeShared {
|
|
|
|
if err = ws.setSharedFormula(*o.Ref); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2019-09-22 20:52:01 +08:00
|
|
|
}
|
|
|
|
if o.Ref != nil {
|
|
|
|
cellData.F.Ref = *o.Ref
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
|
2021-09-03 22:51:56 +08:00
|
|
|
// setSharedFormula set shared formula for the cells.
|
|
|
|
func (ws *xlsxWorksheet) setSharedFormula(ref string) error {
|
|
|
|
coordinates, err := areaRefToCoordinates(ref)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
_ = sortCoordinates(coordinates)
|
|
|
|
cnt := ws.countSharedFormula()
|
|
|
|
for c := coordinates[0]; c <= coordinates[2]; c++ {
|
|
|
|
for r := coordinates[1]; r <= coordinates[3]; r++ {
|
|
|
|
prepareSheetXML(ws, c, r)
|
|
|
|
cell := &ws.SheetData.Row[r-1].C[c-1]
|
|
|
|
if cell.F == nil {
|
|
|
|
cell.F = &xlsxF{}
|
|
|
|
}
|
|
|
|
cell.F.T = STCellFormulaTypeShared
|
|
|
|
cell.F.Si = &cnt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// countSharedFormula count shared formula in the given worksheet.
|
|
|
|
func (ws *xlsxWorksheet) countSharedFormula() (count int) {
|
|
|
|
for _, row := range ws.SheetData.Row {
|
|
|
|
for _, cell := range row.C {
|
|
|
|
if cell.F != nil && cell.F.Si != nil && *cell.F.Si+1 > count {
|
|
|
|
count = *cell.F.Si + 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// GetCellHyperLink provides a function to get cell hyperlink by given
|
2022-01-09 00:20:42 +08:00
|
|
|
// worksheet name and axis. Boolean type value link will be true if the cell
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// has a hyperlink and the target is the address of the hyperlink. Otherwise,
|
|
|
|
// the value of link will be false and the value of the target will be a blank
|
|
|
|
// string. For example get hyperlink of Sheet1!H6:
|
|
|
|
//
|
2019-04-20 14:57:50 +08:00
|
|
|
// link, target, err := f.GetCellHyperLink("Sheet1", "H6")
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) GetCellHyperLink(sheet, axis string) (bool, string, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// Check for correct cell name
|
|
|
|
if _, _, err := SplitCellName(axis); err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, "", err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return false, "", err
|
|
|
|
}
|
2021-08-13 01:32:44 +08:00
|
|
|
if axis, err = f.mergeCellsParser(ws, axis); err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, "", err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
if ws.Hyperlinks != nil {
|
|
|
|
for _, link := range ws.Hyperlinks.Hyperlink {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if link.Ref == axis {
|
|
|
|
if link.RID != "" {
|
2019-03-23 20:08:06 +08:00
|
|
|
return true, f.getSheetRelationshipsTargetByID(sheet, link.RID), err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return true, link.Location, err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2017-01-19 14:05:32 +08:00
|
|
|
}
|
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, "", err
|
2017-01-19 14:05:32 +08:00
|
|
|
}
|
2017-01-23 16:15:01 +08:00
|
|
|
|
2021-03-03 20:30:31 +08:00
|
|
|
// HyperlinkOpts can be passed to SetCellHyperlink to set optional hyperlink
|
|
|
|
// attributes (e.g. display value)
|
|
|
|
type HyperlinkOpts struct {
|
|
|
|
Display *string
|
|
|
|
Tooltip *string
|
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// SetCellHyperLink provides a function to set cell hyperlink by given
|
|
|
|
// worksheet name and link URL address. LinkType defines two types of
|
|
|
|
// hyperlink "External" for web site or "Location" for moving to one of cell
|
2019-04-21 00:04:42 +08:00
|
|
|
// in this workbook. Maximum limit hyperlinks in a worksheet is 65530. The
|
|
|
|
// below is example for external link.
|
2017-07-26 18:37:00 +08:00
|
|
|
//
|
2022-01-05 00:13:29 +08:00
|
|
|
// if err := f.SetCellHyperLink("Sheet1", "A3",
|
|
|
|
// "https://github.com/xuri/excelize", "External"); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// }
|
2017-07-26 18:37:00 +08:00
|
|
|
// // Set underline and font color style for the cell.
|
2022-01-05 00:13:29 +08:00
|
|
|
// style, err := f.NewStyle(&excelize.Style{
|
|
|
|
// Font: &excelize.Font{Color: "#1265BE", Underline: "single"},
|
|
|
|
// })
|
|
|
|
// if err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// }
|
2019-04-20 14:57:50 +08:00
|
|
|
// err = f.SetCellStyle("Sheet1", "A3", "A3", style)
|
2017-07-26 18:37:00 +08:00
|
|
|
//
|
2017-07-30 15:46:04 +08:00
|
|
|
// A this is another example for "Location":
|
2017-07-30 13:52:37 +08:00
|
|
|
//
|
2019-04-20 14:57:50 +08:00
|
|
|
// err := f.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
|
2017-07-30 15:46:04 +08:00
|
|
|
//
|
2021-03-03 20:30:31 +08:00
|
|
|
func (f *File) SetCellHyperLink(sheet, axis, link, linkType string, opts ...HyperlinkOpts) error {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// Check for correct cell name
|
|
|
|
if _, _, err := SplitCellName(axis); err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2017-07-30 15:46:04 +08:00
|
|
|
}
|
2017-01-25 15:44:18 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-08-13 01:32:44 +08:00
|
|
|
if axis, err = f.mergeCellsParser(ws, axis); err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
|
|
|
|
var linkData xlsxHyperlink
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
if ws.Hyperlinks == nil {
|
|
|
|
ws.Hyperlinks = new(xlsxHyperlinks)
|
2019-04-21 00:04:42 +08:00
|
|
|
}
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
if len(ws.Hyperlinks.Hyperlink) > TotalSheetHyperlinks {
|
2021-05-10 00:09:24 +08:00
|
|
|
return ErrTotalSheetHyperlinks
|
2019-04-21 00:04:42 +08:00
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
switch linkType {
|
|
|
|
case "External":
|
|
|
|
linkData = xlsxHyperlink{
|
|
|
|
Ref: axis,
|
2017-08-08 20:08:54 +08:00
|
|
|
}
|
2019-12-23 00:07:40 +08:00
|
|
|
sheetPath := f.sheetMap[trimSheetName(sheet)]
|
2019-09-16 01:17:35 +08:00
|
|
|
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
|
|
|
|
rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
linkData.RID = "rId" + strconv.Itoa(rID)
|
2020-07-18 15:15:16 +08:00
|
|
|
f.addSheetNameSpace(sheet, SourceRelationship)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
case "Location":
|
|
|
|
linkData = xlsxHyperlink{
|
|
|
|
Ref: axis,
|
|
|
|
Location: link,
|
|
|
|
}
|
|
|
|
default:
|
2019-03-23 20:08:06 +08:00
|
|
|
return fmt.Errorf("invalid link type %q", linkType)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
|
2021-03-03 20:30:31 +08:00
|
|
|
for _, o := range opts {
|
|
|
|
if o.Display != nil {
|
|
|
|
linkData.Display = *o.Display
|
|
|
|
}
|
|
|
|
if o.Tooltip != nil {
|
|
|
|
linkData.Tooltip = *o.Tooltip
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, linkData)
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil
|
2017-08-08 20:08:54 +08:00
|
|
|
}
|
|
|
|
|
2021-02-22 20:04:13 +08:00
|
|
|
// GetCellRichText provides a function to get rich text of cell by given
|
|
|
|
// worksheet.
|
|
|
|
func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err error) {
|
|
|
|
ws, err := f.workSheetReader(sheet)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cellData, _, _, err := f.prepareCell(ws, sheet, cell)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
siIdx, err := strconv.Atoi(cellData.V)
|
|
|
|
if nil != err {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
sst := f.sharedStringsReader()
|
|
|
|
if len(sst.SI) <= siIdx || siIdx < 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
si := sst.SI[siIdx]
|
|
|
|
for _, v := range si.R {
|
|
|
|
run := RichTextRun{
|
|
|
|
Text: v.T.Val,
|
|
|
|
}
|
|
|
|
if nil != v.RPr {
|
2021-02-24 00:37:44 +08:00
|
|
|
font := Font{Underline: "none"}
|
2021-02-22 20:04:13 +08:00
|
|
|
font.Bold = v.RPr.B != nil
|
|
|
|
font.Italic = v.RPr.I != nil
|
2021-02-24 00:37:44 +08:00
|
|
|
if v.RPr.U != nil {
|
|
|
|
font.Underline = "single"
|
|
|
|
if v.RPr.U.Val != nil {
|
|
|
|
font.Underline = *v.RPr.U.Val
|
|
|
|
}
|
2021-02-22 20:04:13 +08:00
|
|
|
}
|
2021-02-23 00:05:19 +08:00
|
|
|
if v.RPr.RFont != nil && v.RPr.RFont.Val != nil {
|
2021-02-22 20:04:13 +08:00
|
|
|
font.Family = *v.RPr.RFont.Val
|
|
|
|
}
|
2021-02-23 00:05:19 +08:00
|
|
|
if v.RPr.Sz != nil && v.RPr.Sz.Val != nil {
|
2021-02-22 20:04:13 +08:00
|
|
|
font.Size = *v.RPr.Sz.Val
|
|
|
|
}
|
|
|
|
font.Strike = v.RPr.Strike != nil
|
|
|
|
if nil != v.RPr.Color {
|
|
|
|
font.Color = strings.TrimPrefix(v.RPr.Color.RGB, "FF")
|
|
|
|
}
|
|
|
|
run.Font = &font
|
|
|
|
}
|
|
|
|
runs = append(runs, run)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-27 23:34:14 +08:00
|
|
|
// newRpr create run properties for the rich text by given font format.
|
|
|
|
func newRpr(fnt *Font) *xlsxRPr {
|
|
|
|
rpr := xlsxRPr{}
|
|
|
|
trueVal := ""
|
|
|
|
if fnt.Bold {
|
|
|
|
rpr.B = &trueVal
|
|
|
|
}
|
|
|
|
if fnt.Italic {
|
|
|
|
rpr.I = &trueVal
|
|
|
|
}
|
|
|
|
if fnt.Strike {
|
|
|
|
rpr.Strike = &trueVal
|
|
|
|
}
|
|
|
|
if fnt.Underline != "" {
|
|
|
|
rpr.U = &attrValString{Val: &fnt.Underline}
|
|
|
|
}
|
|
|
|
if fnt.Family != "" {
|
|
|
|
rpr.RFont = &attrValString{Val: &fnt.Family}
|
|
|
|
}
|
|
|
|
if fnt.Size > 0.0 {
|
|
|
|
rpr.Sz = &attrValFloat{Val: &fnt.Size}
|
|
|
|
}
|
|
|
|
if fnt.Color != "" {
|
|
|
|
rpr.Color = &xlsxColor{RGB: getPaletteColor(fnt.Color)}
|
|
|
|
}
|
|
|
|
return &rpr
|
|
|
|
}
|
|
|
|
|
2020-04-06 00:23:27 +08:00
|
|
|
// SetCellRichText provides a function to set cell with rich text by given
|
2020-04-09 01:00:14 +08:00
|
|
|
// worksheet. For example, set rich text on the A1 cell of the worksheet named
|
|
|
|
// Sheet1:
|
2017-01-25 15:44:18 +08:00
|
|
|
//
|
2020-04-06 00:23:27 +08:00
|
|
|
// package main
|
2017-01-25 15:44:18 +08:00
|
|
|
//
|
2020-04-06 00:23:27 +08:00
|
|
|
// import (
|
|
|
|
// "fmt"
|
|
|
|
//
|
2021-07-28 00:38:09 +08:00
|
|
|
// "github.com/xuri/excelize/v2"
|
2020-04-06 00:23:27 +08:00
|
|
|
// )
|
|
|
|
//
|
|
|
|
// func main() {
|
|
|
|
// f := excelize.NewFile()
|
|
|
|
// if err := f.SetRowHeight("Sheet1", 1, 35); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// if err := f.SetColWidth("Sheet1", "A", "A", 44); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// if err := f.SetCellRichText("Sheet1", "A1", []excelize.RichTextRun{
|
|
|
|
// {
|
2020-08-22 18:58:43 +08:00
|
|
|
// Text: "bold",
|
2020-04-06 00:23:27 +08:00
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Bold: true,
|
|
|
|
// Color: "2354e8",
|
|
|
|
// Family: "Times New Roman",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: " and ",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Family: "Times New Roman",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: " italic",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Bold: true,
|
|
|
|
// Color: "e83723",
|
|
|
|
// Italic: true,
|
|
|
|
// Family: "Times New Roman",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: "text with color and font-family,",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Bold: true,
|
|
|
|
// Color: "2354e8",
|
|
|
|
// Family: "Times New Roman",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: "\r\nlarge text with ",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Size: 14,
|
|
|
|
// Color: "ad23e8",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: "strike",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Color: "e89923",
|
|
|
|
// Strike: true,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: " and ",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Size: 14,
|
|
|
|
// Color: "ad23e8",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// Text: "underline.",
|
|
|
|
// Font: &excelize.Font{
|
|
|
|
// Color: "23e833",
|
|
|
|
// Underline: "single",
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// }); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// style, err := f.NewStyle(&excelize.Style{
|
|
|
|
// Alignment: &excelize.Alignment{
|
|
|
|
// WrapText: true,
|
|
|
|
// },
|
|
|
|
// })
|
|
|
|
// if err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// if err := f.SetCellStyle("Sheet1", "A1", "A1", style); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// if err := f.SaveAs("Book1.xlsx"); err != nil {
|
|
|
|
// fmt.Println(err)
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
|
|
|
|
ws, err := f.workSheetReader(sheet)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2020-04-06 00:23:27 +08:00
|
|
|
cellData, col, _, err := f.prepareCell(ws, sheet, cell)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-12-27 23:34:14 +08:00
|
|
|
if err := f.sharedStringsLoader(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-04-06 00:23:27 +08:00
|
|
|
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
|
|
|
si := xlsxSI{}
|
|
|
|
sst := f.sharedStringsReader()
|
|
|
|
textRuns := []xlsxR{}
|
2021-07-31 14:20:29 +08:00
|
|
|
totalCellChars := 0
|
2020-04-06 00:23:27 +08:00
|
|
|
for _, textRun := range runs {
|
2021-07-31 14:20:29 +08:00
|
|
|
totalCellChars += len(textRun.Text)
|
|
|
|
if totalCellChars > TotalCellChars {
|
|
|
|
return ErrCellCharsLength
|
2020-04-06 00:23:27 +08:00
|
|
|
}
|
2021-07-31 14:20:29 +08:00
|
|
|
run := xlsxR{T: &xlsxT{}}
|
|
|
|
_, run.T.Val, run.T.Space = setCellStr(textRun.Text)
|
2020-04-06 00:23:27 +08:00
|
|
|
fnt := textRun.Font
|
|
|
|
if fnt != nil {
|
2021-12-27 23:34:14 +08:00
|
|
|
run.RPr = newRpr(fnt)
|
2020-04-06 00:23:27 +08:00
|
|
|
}
|
|
|
|
textRuns = append(textRuns, run)
|
|
|
|
}
|
|
|
|
si.R = textRuns
|
This closes #787, avoid duplicate rich text string items, new formula fn: BIN2DEC, BIN2HEX, BIN2OCT, HEX2BIN, HEX2DEC, HEX2OCT, OCT2BIN, OCT2DEC, OCT2HEX
2021-02-21 00:21:45 +08:00
|
|
|
for idx, strItem := range sst.SI {
|
|
|
|
if reflect.DeepEqual(strItem, si) {
|
|
|
|
cellData.T, cellData.V = "s", strconv.Itoa(idx)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2020-04-06 00:23:27 +08:00
|
|
|
sst.SI = append(sst.SI, si)
|
|
|
|
sst.Count++
|
|
|
|
sst.UniqueCount++
|
|
|
|
cellData.T, cellData.V = "s", strconv.Itoa(len(sst.SI)-1)
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2017-01-25 15:44:18 +08:00
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// SetSheetRow writes an array to row by given worksheet name, starting
|
|
|
|
// coordinate and a pointer to array type 'slice'. For example, writes an
|
|
|
|
// array to row 6 start with the cell B6 on Sheet1:
|
|
|
|
//
|
2019-04-20 14:57:50 +08:00
|
|
|
// err := f.SetSheetRow("Sheet1", "B6", &[]interface{}{"1", nil, 2})
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
//
|
2019-03-23 20:08:06 +08:00
|
|
|
func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
col, row, err := CellNameToCoordinates(axis)
|
2017-09-19 11:59:33 +08:00
|
|
|
if err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2017-09-19 11:59:33 +08:00
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// Make sure 'slice' is a Ptr to Slice
|
|
|
|
v := reflect.ValueOf(slice)
|
|
|
|
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Slice {
|
2021-07-05 00:03:56 +08:00
|
|
|
return ErrParameterInvalid
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
v = v.Elem()
|
2017-07-24 10:26:02 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
cell, err := CoordinatesToCellName(col+i, row)
|
2019-08-19 15:53:56 +08:00
|
|
|
// Error should never happens here. But keep checking to early detect regresions
|
|
|
|
// if it will be introduced in future.
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
2019-08-19 15:53:56 +08:00
|
|
|
if err := f.SetCellValue(sheet, cell, v.Index(i).Interface()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return err
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// getCellInfo does common preparation for all SetCell* methods.
|
2020-11-10 23:48:09 +08:00
|
|
|
func (f *File) prepareCell(ws *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int, error) {
|
2019-03-23 20:08:06 +08:00
|
|
|
var err error
|
2020-11-10 23:48:09 +08:00
|
|
|
cell, err = f.mergeCellsParser(ws, cell)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, 0, 0, err
|
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
col, row, err := CellNameToCoordinates(cell)
|
2017-09-19 11:59:33 +08:00
|
|
|
if err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return nil, 0, 0, err
|
2017-09-19 11:59:33 +08:00
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
prepareSheetXML(ws, col, row)
|
2021-07-05 00:03:56 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-11-10 23:48:09 +08:00
|
|
|
return &ws.SheetData.Row[row-1].C[col-1], col, row, err
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
2019-03-23 20:08:06 +08:00
|
|
|
// getCellStringFunc does common value extraction workflow for all GetCell*
|
|
|
|
// methods. Passed function implements specific part of required logic.
|
|
|
|
func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c *xlsxC) (string, bool, error)) (string, error) {
|
2020-11-10 23:48:09 +08:00
|
|
|
ws, err := f.workSheetReader(sheet)
|
2019-04-15 11:22:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
axis, err = f.mergeCellsParser(ws, axis)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
_, row, err := CellNameToCoordinates(axis)
|
2017-09-19 11:59:33 +08:00
|
|
|
if err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return "", err
|
2017-09-19 11:59:33 +08:00
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
ws.Lock()
|
|
|
|
defer ws.Unlock()
|
2020-08-15 00:09:50 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
lastRowNum := 0
|
2020-11-10 23:48:09 +08:00
|
|
|
if l := len(ws.SheetData.Row); l > 0 {
|
|
|
|
lastRowNum = ws.SheetData.Row[l-1].R
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// keep in mind: row starts from 1
|
|
|
|
if row > lastRowNum {
|
2019-03-23 20:08:06 +08:00
|
|
|
return "", nil
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2017-07-24 10:26:02 +08:00
|
|
|
|
2020-11-10 23:48:09 +08:00
|
|
|
for rowIdx := range ws.SheetData.Row {
|
|
|
|
rowData := &ws.SheetData.Row[rowIdx]
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if rowData.R != row {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for colIdx := range rowData.C {
|
|
|
|
colData := &rowData.C[colIdx]
|
|
|
|
if axis != colData.R {
|
|
|
|
continue
|
|
|
|
}
|
2020-11-10 23:48:09 +08:00
|
|
|
val, ok, err := fn(ws, colData)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if ok {
|
|
|
|
return val, nil
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return "", nil
|
2017-07-24 10:26:02 +08:00
|
|
|
}
|
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// formattedValue provides a function to returns a value after formatted. If
|
|
|
|
// it is possible to apply a format to the cell value, it will do so, if not
|
|
|
|
// then an error will be returned, along with the raw value of the cell.
|
2021-09-05 11:59:50 +08:00
|
|
|
func (f *File) formattedValue(s int, v string, raw bool) string {
|
2021-09-26 00:07:40 +08:00
|
|
|
precise := v
|
|
|
|
isNum, precision := isNumeric(v)
|
|
|
|
if isNum && precision > 10 {
|
2021-10-15 21:45:46 +08:00
|
|
|
precise = roundPrecision(v, -1)
|
|
|
|
}
|
|
|
|
if raw {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
if !isNum {
|
|
|
|
v = roundPrecision(v, 15)
|
|
|
|
precise = v
|
2021-09-26 00:07:40 +08:00
|
|
|
}
|
2021-10-15 21:45:46 +08:00
|
|
|
if s == 0 {
|
2021-09-26 00:07:40 +08:00
|
|
|
return precise
|
2018-03-12 20:14:39 +08:00
|
|
|
}
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
styleSheet := f.stylesReader()
|
2020-12-12 16:17:00 +08:00
|
|
|
|
2020-10-04 21:07:39 +08:00
|
|
|
if s >= len(styleSheet.CellXfs.Xf) {
|
2021-09-26 00:07:40 +08:00
|
|
|
return precise
|
2020-10-04 21:07:39 +08:00
|
|
|
}
|
2020-12-12 16:17:00 +08:00
|
|
|
var numFmtID int
|
|
|
|
if styleSheet.CellXfs.Xf[s].NumFmtID != nil {
|
|
|
|
numFmtID = *styleSheet.CellXfs.Xf[s].NumFmtID
|
|
|
|
}
|
|
|
|
|
2020-11-23 00:01:06 +08:00
|
|
|
ok := builtInNumFmtFunc[numFmtID]
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if ok != nil {
|
2021-10-15 21:45:46 +08:00
|
|
|
return ok(precise, builtInNumFmt[numFmtID])
|
2020-10-04 21:07:39 +08:00
|
|
|
}
|
2020-10-19 23:55:54 +08:00
|
|
|
if styleSheet == nil || styleSheet.NumFmts == nil {
|
2021-09-26 00:07:40 +08:00
|
|
|
return precise
|
2020-10-19 23:55:54 +08:00
|
|
|
}
|
2020-10-04 21:07:39 +08:00
|
|
|
for _, xlsxFmt := range styleSheet.NumFmts.NumFmt {
|
2020-11-23 00:01:06 +08:00
|
|
|
if xlsxFmt.NumFmtID == numFmtID {
|
2020-10-04 21:07:39 +08:00
|
|
|
format := strings.ToLower(xlsxFmt.FormatCode)
|
2021-09-26 00:07:40 +08:00
|
|
|
if isTimeNumFmt(format) {
|
2020-10-04 21:07:39 +08:00
|
|
|
return parseTime(v, format)
|
|
|
|
}
|
2021-09-26 00:07:40 +08:00
|
|
|
return precise
|
2020-10-04 21:07:39 +08:00
|
|
|
}
|
2018-03-12 20:14:39 +08:00
|
|
|
}
|
2021-09-26 00:07:40 +08:00
|
|
|
return precise
|
|
|
|
}
|
|
|
|
|
|
|
|
// isTimeNumFmt determine if the given number format expression is a time number format.
|
|
|
|
func isTimeNumFmt(format string) bool {
|
|
|
|
return strings.Contains(format, "y") || strings.Contains(format, "m") || strings.Contains(strings.Replace(format, "red", "", -1), "d") || strings.Contains(format, "h")
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2018-03-12 20:14:39 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// prepareCellStyle provides a function to prepare style index of cell in
|
|
|
|
// worksheet by given column index and style index.
|
2020-11-10 23:48:09 +08:00
|
|
|
func (f *File) prepareCellStyle(ws *xlsxWorksheet, col, style int) int {
|
|
|
|
if ws.Cols != nil && style == 0 {
|
|
|
|
for _, c := range ws.Cols.Col {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
if c.Min <= col && col <= c.Max {
|
|
|
|
style = c.Style
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return style
|
|
|
|
}
|
2018-03-12 20:14:39 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// mergeCellsParser provides a function to check merged cells in worksheet by
|
|
|
|
// given axis.
|
2020-11-10 23:48:09 +08:00
|
|
|
func (f *File) mergeCellsParser(ws *xlsxWorksheet, axis string) (string, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
axis = strings.ToUpper(axis)
|
2020-11-10 23:48:09 +08:00
|
|
|
if ws.MergeCells != nil {
|
|
|
|
for i := 0; i < len(ws.MergeCells.Cells); i++ {
|
|
|
|
ok, err := f.checkCellInArea(axis, ws.MergeCells.Cells[i].Ref)
|
2019-03-23 20:08:06 +08:00
|
|
|
if err != nil {
|
|
|
|
return axis, err
|
|
|
|
}
|
|
|
|
if ok {
|
2020-11-10 23:48:09 +08:00
|
|
|
axis = strings.Split(ws.MergeCells.Cells[i].Ref, ":")[0]
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
}
|
2018-03-12 20:14:39 +08:00
|
|
|
}
|
2019-03-23 20:08:06 +08:00
|
|
|
return axis, nil
|
2018-03-12 20:14:39 +08:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:21:24 +08:00
|
|
|
// checkCellInArea provides a function to determine if a given coordinate is
|
2017-01-25 15:44:18 +08:00
|
|
|
// within an area.
|
2019-12-14 19:57:37 +08:00
|
|
|
func (f *File) checkCellInArea(cell, area string) (bool, error) {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
col, row, err := CellNameToCoordinates(cell)
|
|
|
|
if err != nil {
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, err
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2017-01-25 15:44:18 +08:00
|
|
|
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
rng := strings.Split(area, ":")
|
|
|
|
if len(rng) != 2 {
|
2019-03-23 20:08:06 +08:00
|
|
|
return false, err
|
2018-04-08 10:31:11 +08:00
|
|
|
}
|
2021-08-13 01:32:44 +08:00
|
|
|
coordinates, err := areaRefToCoordinates(area)
|
2019-12-14 19:57:37 +08:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
2018-04-08 10:31:11 +08:00
|
|
|
|
2019-12-14 19:57:37 +08:00
|
|
|
return cellInRef([]int{col, row}, coordinates), err
|
|
|
|
}
|
2018-04-08 10:31:11 +08:00
|
|
|
|
2019-12-14 19:57:37 +08:00
|
|
|
// cellInRef provides a function to determine if a given range is within an
|
|
|
|
// range.
|
|
|
|
func cellInRef(cell, ref []int) bool {
|
|
|
|
return cell[0] >= ref[0] && cell[0] <= ref[2] && cell[1] >= ref[1] && cell[1] <= ref[3]
|
|
|
|
}
|
2017-01-25 15:44:18 +08:00
|
|
|
|
2019-12-14 19:57:37 +08:00
|
|
|
// isOverlap find if the given two rectangles overlap or not.
|
|
|
|
func isOverlap(rect1, rect2 []int) bool {
|
|
|
|
return cellInRef([]int{rect1[0], rect1[1]}, rect2) ||
|
|
|
|
cellInRef([]int{rect1[2], rect1[1]}, rect2) ||
|
|
|
|
cellInRef([]int{rect1[0], rect1[3]}, rect2) ||
|
|
|
|
cellInRef([]int{rect1[2], rect1[3]}, rect2) ||
|
|
|
|
cellInRef([]int{rect2[0], rect2[1]}, rect1) ||
|
|
|
|
cellInRef([]int{rect2[2], rect2[1]}, rect1) ||
|
|
|
|
cellInRef([]int{rect2[0], rect2[3]}, rect1) ||
|
|
|
|
cellInRef([]int{rect2[2], rect2[3]}, rect1)
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
2017-01-25 15:44:18 +08:00
|
|
|
|
2021-08-15 01:19:49 +08:00
|
|
|
// parseSharedFormula generate dynamic part of shared formula for target cell
|
|
|
|
// by given column and rows distance and origin shared formula.
|
|
|
|
func parseSharedFormula(dCol, dRow int, orig []byte) (res string, start int) {
|
|
|
|
var (
|
|
|
|
end int
|
|
|
|
stringLiteral bool
|
|
|
|
)
|
|
|
|
for end = 0; end < len(orig); end++ {
|
|
|
|
c := orig[end]
|
|
|
|
if c == '"' {
|
|
|
|
stringLiteral = !stringLiteral
|
|
|
|
}
|
|
|
|
if stringLiteral {
|
|
|
|
continue // Skip characters in quotes
|
|
|
|
}
|
|
|
|
if c >= 'A' && c <= 'Z' || c == '$' {
|
|
|
|
res += string(orig[start:end])
|
|
|
|
start = end
|
|
|
|
end++
|
|
|
|
foundNum := false
|
|
|
|
for ; end < len(orig); end++ {
|
|
|
|
idc := orig[end]
|
|
|
|
if idc >= '0' && idc <= '9' || idc == '$' {
|
|
|
|
foundNum = true
|
|
|
|
} else if idc >= 'A' && idc <= 'Z' {
|
|
|
|
if foundNum {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if foundNum {
|
|
|
|
cellID := string(orig[start:end])
|
|
|
|
res += shiftCell(cellID, dCol, dRow)
|
|
|
|
start = end
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-01-09 00:20:42 +08:00
|
|
|
// getSharedFormula find a cell contains the same formula as another cell,
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
// the "shared" value can be used for the t attribute and the si attribute can
|
|
|
|
// be used to refer to the cell containing the formula. Two formulas are
|
|
|
|
// considered to be the same when their respective representations in
|
|
|
|
// R1C1-reference notation, are the same.
|
|
|
|
//
|
|
|
|
// Note that this function not validate ref tag to check the cell if or not in
|
|
|
|
// allow area, and always return origin shared formula.
|
2022-01-09 00:20:42 +08:00
|
|
|
func getSharedFormula(ws *xlsxWorksheet, si int, axis string) string {
|
2020-11-10 23:48:09 +08:00
|
|
|
for _, r := range ws.SheetData.Row {
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
for _, c := range r.C {
|
2021-09-03 22:51:56 +08:00
|
|
|
if c.F != nil && c.F.Ref != "" && c.F.T == STCellFormulaTypeShared && c.F.Si != nil && *c.F.Si == si {
|
2021-08-15 01:19:49 +08:00
|
|
|
col, row, _ := CellNameToCoordinates(axis)
|
|
|
|
sharedCol, sharedRow, _ := CellNameToCoordinates(c.R)
|
|
|
|
dCol := col - sharedCol
|
|
|
|
dRow := row - sharedRow
|
|
|
|
orig := []byte(c.F.Content)
|
|
|
|
res, start := parseSharedFormula(dCol, dRow, orig)
|
|
|
|
if start < len(orig) {
|
|
|
|
res += string(orig[start:])
|
|
|
|
}
|
|
|
|
return res
|
Huge refactorig for consistent col/row numbering (#356)
* Huge refactorig for consistent col/row numbering
Started from simply changing ToALphaString()/TitleToNumber() logic and related fixes.
But have to go deeper, do fixes, after do related fixes and again and again.
Major improvements:
1. Tests made stronger again (But still be weak).
2. "Empty" returns for incorrect input replaces with panic.
3. Check for correct col/row/cell naming & addressing by default.
4. Removed huge amount of duplicated code.
5. Removed ToALphaString(), TitleToNumber() and it helpers functions at all,
and replaced with SplitCellName(), JoinCellName(), ColumnNameToNumber(), ColumnNumberToName(), CellNameToCoordinates(), CoordinatesToCellName().
6. Minor fixes for internal variable naming for code readability (ex. col, row for input params, colIdx, rowIdx for slice indexes etc).
* Formatting fixes
2019-03-20 00:14:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
2017-01-25 15:44:18 +08:00
|
|
|
}
|
2021-08-15 01:19:49 +08:00
|
|
|
|
|
|
|
// shiftCell returns the cell shifted according to dCol and dRow taking into
|
|
|
|
// consideration of absolute references with dollar sign ($)
|
|
|
|
func shiftCell(cellID string, dCol, dRow int) string {
|
|
|
|
fCol, fRow, _ := CellNameToCoordinates(cellID)
|
|
|
|
signCol, signRow := "", ""
|
|
|
|
if strings.Index(cellID, "$") == 0 {
|
|
|
|
signCol = "$"
|
|
|
|
} else {
|
|
|
|
// Shift column
|
|
|
|
fCol += dCol
|
|
|
|
}
|
|
|
|
if strings.LastIndex(cellID, "$") > 0 {
|
|
|
|
signRow = "$"
|
|
|
|
} else {
|
|
|
|
// Shift row
|
|
|
|
fRow += dRow
|
|
|
|
}
|
|
|
|
colName, _ := ColumnNumberToName(fCol)
|
|
|
|
return signCol + colName + signRow + strconv.Itoa(fRow)
|
|
|
|
}
|