This closes #1468, checks the table name, and added a new error constant `ErrTableNameLength`

- XML Structure field typo fixed
- Update documentation for the `AddChart` function
- Update unit test
This commit is contained in:
xuri 2023-02-13 13:28:02 +08:00 committed by GitHub
parent 38f131728b
commit 363fa940ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 13 deletions

View File

@ -773,7 +773,7 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
// The 'ShowVal' property is optional. The default value is false.
//
// Set the primary horizontal and vertical axis options by 'XAxis' and 'YAxis'.
// The properties of XAxis that can be set are:
// The properties of 'XAxis' that can be set are:
//
// None
// MajorGridLines
@ -790,13 +790,12 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
// MajorGridLines
// MinorGridLines
// MajorUnit
// TickLabelSkip
// ReverseOrder
// Maximum
// Minimum
// Font
//
// none: Disable axes.
// None: Disable axes.
//
// MajorGridLines: Specifies major grid lines.
//

View File

@ -40,6 +40,12 @@ func newInvalidExcelDateError(dateValue float64) error {
return fmt.Errorf("invalid date value %f, negative values are not supported", dateValue)
}
// newInvalidTableNameError defined the error message on receiving the invalid
// table name.
func newInvalidTableNameError(name string) error {
return fmt.Errorf("invalid table name %q", name)
}
// newUnsupportedChartType defined the error message on receiving the chart
// type are unsupported.
func newUnsupportedChartType(chartType string) error {
@ -230,6 +236,9 @@ var (
// ErrSheetNameLength defined the error message on receiving the sheet
// name length exceeds the limit.
ErrSheetNameLength = fmt.Errorf("the sheet name length exceeds the %d characters limit", MaxSheetNameLength)
// ErrTableNameLength defined the error message on receiving the table name
// length exceeds the limit.
ErrTableNameLength = fmt.Errorf("the table name length exceeds the %d characters limit", MaxFieldLength)
// ErrCellStyles defined the error message on cell styles exceeds the limit.
ErrCellStyles = fmt.Errorf("the cell styles exceeds the %d limit", MaxCellStyles)
// ErrUnprotectWorkbook defined the error message on workbook has set no

View File

@ -110,14 +110,14 @@ func parseGraphicOptions(opts *GraphicOptions) *GraphicOptions {
// }
// }
//
// The optional parameter "Autofit" specifies if you make image size auto-fits the
// The optional parameter "AutoFit" specifies if you make image size auto-fits the
// cell, the default value of that is 'false'.
//
// The optional parameter "Hyperlink" specifies the hyperlink of the image.
//
// The optional parameter "HyperlinkType" defines two types of
// hyperlink "External" for website or "Location" for moving to one of the
// cells in this workbook. When the "hyperlink_type" is "Location",
// cells in this workbook. When the "HyperlinkType" is "Location",
// coordinates need to start with "#".
//
// The optional parameter "Positioning" defines two types of the position of an

View File

@ -161,7 +161,10 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
//
// See File.AddTable for details on the table format.
func (sw *StreamWriter) AddTable(rangeRef string, opts *TableOptions) error {
options := parseTableOptions(opts)
options, err := parseTableOptions(opts)
if err != nil {
return err
}
coordinates, err := rangeRefToCoordinates(rangeRef)
if err != nil {
return err

View File

@ -222,6 +222,8 @@ func TestStreamTable(t *testing.T) {
// Test add table with illegal cell reference
assert.EqualError(t, streamWriter.AddTable("A:B1", nil), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
assert.EqualError(t, streamWriter.AddTable("A1:B", nil), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")).Error())
// Test add table with invalid table name
assert.EqualError(t, streamWriter.AddTable("A:B1", &TableOptions{Name: "1Table"}), newInvalidTableNameError("1Table").Error())
// Test add table with unsupported charset content types
file.ContentTypes = nil
file.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)

View File

@ -17,18 +17,24 @@ import (
"regexp"
"strconv"
"strings"
"unicode"
"unicode/utf8"
)
// parseTableOptions provides a function to parse the format settings of the
// table with default value.
func parseTableOptions(opts *TableOptions) *TableOptions {
func parseTableOptions(opts *TableOptions) (*TableOptions, error) {
var err error
if opts == nil {
return &TableOptions{ShowRowStripes: boolPtr(true)}
return &TableOptions{ShowRowStripes: boolPtr(true)}, err
}
if opts.ShowRowStripes == nil {
opts.ShowRowStripes = boolPtr(true)
}
return opts
if err = checkTableName(opts.Name); err != nil {
return opts, err
}
return opts, err
}
// AddTable provides the method to add table in a worksheet by given worksheet
@ -54,7 +60,9 @@ func parseTableOptions(opts *TableOptions) *TableOptions {
// header row data of the table before calling the AddTable function. Multiple
// tables range reference that can't have an intersection.
//
// Name: The name of the table, in the same worksheet name of the table should be unique
// Name: The name of the table, in the same worksheet name of the table should
// be unique, starts with a letter or underscore (_), doesn't include a
// space or character, and should be no more than 255 characters
//
// StyleName: The built-in table style names
//
@ -62,7 +70,10 @@ func parseTableOptions(opts *TableOptions) *TableOptions {
// TableStyleMedium1 - TableStyleMedium28
// TableStyleDark1 - TableStyleDark11
func (f *File) AddTable(sheet, rangeRef string, opts *TableOptions) error {
options := parseTableOptions(opts)
options, err := parseTableOptions(opts)
if err != nil {
return err
}
// Coordinate conversion, convert C1:B3 to 2,0,1,2.
coordinates, err := rangeRefToCoordinates(rangeRef)
if err != nil {
@ -147,6 +158,29 @@ func (f *File) setTableHeader(sheet string, x1, y1, x2 int) ([]*xlsxTableColumn,
return tableColumns, nil
}
// checkSheetName check whether there are illegal characters in the table name.
// Verify that the name:
// 1. Starts with a letter or underscore (_)
// 2. Doesn't include a space or character that isn't allowed
func checkTableName(name string) error {
if utf8.RuneCountInString(name) > MaxFieldLength {
return ErrTableNameLength
}
for i, c := range name {
if string(c) == "_" {
continue
}
if unicode.IsLetter(c) {
continue
}
if i > 0 && unicode.IsDigit(c) {
continue
}
return newInvalidTableNameError(name)
}
return nil
}
// addTable provides a function to add table by given worksheet name,
// range reference and format set.
func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, opts *TableOptions) error {

View File

@ -3,6 +3,7 @@ package excelize
import (
"fmt"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@ -37,6 +38,24 @@ func TestAddTable(t *testing.T) {
f = NewFile()
assert.EqualError(t, f.addTable("sheet1", "", 0, 0, 0, 0, 0, nil), "invalid cell reference [0, 0]")
assert.EqualError(t, f.addTable("sheet1", "", 1, 1, 0, 0, 0, nil), "invalid cell reference [0, 0]")
// Test add table with invalid table name
for _, cases := range []struct {
name string
err error
}{
{name: "1Table", err: newInvalidTableNameError("1Table")},
{name: "-Table", err: newInvalidTableNameError("-Table")},
{name: "'Table", err: newInvalidTableNameError("'Table")},
{name: "Table 1", err: newInvalidTableNameError("Table 1")},
{name: "A&B", err: newInvalidTableNameError("A&B")},
{name: "_1Table'", err: newInvalidTableNameError("_1Table'")},
{name: "\u0f5f\u0fb3\u0f0b\u0f21", err: newInvalidTableNameError("\u0f5f\u0fb3\u0f0b\u0f21")},
{name: strings.Repeat("c", MaxFieldLength+1), err: ErrTableNameLength},
} {
assert.EqualError(t, f.AddTable("Sheet1", "A1:B2", &TableOptions{
Name: cases.name,
}), cases.err.Error())
}
}
func TestSetTableHeader(t *testing.T) {

View File

@ -766,7 +766,7 @@ type decodeX14ConditionalFormatting struct {
// decodeX14CfRule directly maps the cfRule element.
type decodeX14CfRule struct {
XNLName xml.Name `xml:"cfRule"`
XMLName xml.Name `xml:"cfRule"`
Type string `xml:"type,attr,omitempty"`
ID string `xml:"id,attr,omitempty"`
DataBar *decodeX14DataBar `xml:"dataBar"`
@ -774,7 +774,7 @@ type decodeX14CfRule struct {
// decodeX14DataBar directly maps the dataBar element.
type decodeX14DataBar struct {
XNLName xml.Name `xml:"dataBar"`
XMLName xml.Name `xml:"dataBar"`
MaxLength int `xml:"maxLength,attr"`
MinLength int `xml:"minLength,attr"`
Border bool `xml:"border,attr,omitempty"`