Skip to content

Commit 363fa94

Browse files
authored
This closes qax-os#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
1 parent 38f1317 commit 363fa94

8 files changed

+79
-13
lines changed

chart.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
773773
// The 'ShowVal' property is optional. The default value is false.
774774
//
775775
// Set the primary horizontal and vertical axis options by 'XAxis' and 'YAxis'.
776-
// The properties of XAxis that can be set are:
776+
// The properties of 'XAxis' that can be set are:
777777
//
778778
// None
779779
// MajorGridLines
@@ -790,13 +790,12 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
790790
// MajorGridLines
791791
// MinorGridLines
792792
// MajorUnit
793-
// TickLabelSkip
794793
// ReverseOrder
795794
// Maximum
796795
// Minimum
797796
// Font
798797
//
799-
// none: Disable axes.
798+
// None: Disable axes.
800799
//
801800
// MajorGridLines: Specifies major grid lines.
802801
//

errors.go

+9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ func newInvalidExcelDateError(dateValue float64) error {
4040
return fmt.Errorf("invalid date value %f, negative values are not supported", dateValue)
4141
}
4242

43+
// newInvalidTableNameError defined the error message on receiving the invalid
44+
// table name.
45+
func newInvalidTableNameError(name string) error {
46+
return fmt.Errorf("invalid table name %q", name)
47+
}
48+
4349
// newUnsupportedChartType defined the error message on receiving the chart
4450
// type are unsupported.
4551
func newUnsupportedChartType(chartType string) error {
@@ -230,6 +236,9 @@ var (
230236
// ErrSheetNameLength defined the error message on receiving the sheet
231237
// name length exceeds the limit.
232238
ErrSheetNameLength = fmt.Errorf("the sheet name length exceeds the %d characters limit", MaxSheetNameLength)
239+
// ErrTableNameLength defined the error message on receiving the table name
240+
// length exceeds the limit.
241+
ErrTableNameLength = fmt.Errorf("the table name length exceeds the %d characters limit", MaxFieldLength)
233242
// ErrCellStyles defined the error message on cell styles exceeds the limit.
234243
ErrCellStyles = fmt.Errorf("the cell styles exceeds the %d limit", MaxCellStyles)
235244
// ErrUnprotectWorkbook defined the error message on workbook has set no

picture.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,14 @@ func parseGraphicOptions(opts *GraphicOptions) *GraphicOptions {
110110
// }
111111
// }
112112
//
113-
// The optional parameter "Autofit" specifies if you make image size auto-fits the
113+
// The optional parameter "AutoFit" specifies if you make image size auto-fits the
114114
// cell, the default value of that is 'false'.
115115
//
116116
// The optional parameter "Hyperlink" specifies the hyperlink of the image.
117117
//
118118
// The optional parameter "HyperlinkType" defines two types of
119119
// hyperlink "External" for website or "Location" for moving to one of the
120-
// cells in this workbook. When the "hyperlink_type" is "Location",
120+
// cells in this workbook. When the "HyperlinkType" is "Location",
121121
// coordinates need to start with "#".
122122
//
123123
// The optional parameter "Positioning" defines two types of the position of an

stream.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,10 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
161161
//
162162
// See File.AddTable for details on the table format.
163163
func (sw *StreamWriter) AddTable(rangeRef string, opts *TableOptions) error {
164-
options := parseTableOptions(opts)
164+
options, err := parseTableOptions(opts)
165+
if err != nil {
166+
return err
167+
}
165168
coordinates, err := rangeRefToCoordinates(rangeRef)
166169
if err != nil {
167170
return err

stream_test.go

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

table.go

+39-5
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@ import (
1717
"regexp"
1818
"strconv"
1919
"strings"
20+
"unicode"
21+
"unicode/utf8"
2022
)
2123

2224
// parseTableOptions provides a function to parse the format settings of the
2325
// table with default value.
24-
func parseTableOptions(opts *TableOptions) *TableOptions {
26+
func parseTableOptions(opts *TableOptions) (*TableOptions, error) {
27+
var err error
2528
if opts == nil {
26-
return &TableOptions{ShowRowStripes: boolPtr(true)}
29+
return &TableOptions{ShowRowStripes: boolPtr(true)}, err
2730
}
2831
if opts.ShowRowStripes == nil {
2932
opts.ShowRowStripes = boolPtr(true)
3033
}
31-
return opts
34+
if err = checkTableName(opts.Name); err != nil {
35+
return opts, err
36+
}
37+
return opts, err
3238
}
3339

3440
// AddTable provides the method to add table in a worksheet by given worksheet
@@ -54,15 +60,20 @@ func parseTableOptions(opts *TableOptions) *TableOptions {
5460
// header row data of the table before calling the AddTable function. Multiple
5561
// tables range reference that can't have an intersection.
5662
//
57-
// Name: The name of the table, in the same worksheet name of the table should be unique
63+
// Name: The name of the table, in the same worksheet name of the table should
64+
// be unique, starts with a letter or underscore (_), doesn't include a
65+
// space or character, and should be no more than 255 characters
5866
//
5967
// StyleName: The built-in table style names
6068
//
6169
// TableStyleLight1 - TableStyleLight21
6270
// TableStyleMedium1 - TableStyleMedium28
6371
// TableStyleDark1 - TableStyleDark11
6472
func (f *File) AddTable(sheet, rangeRef string, opts *TableOptions) error {
65-
options := parseTableOptions(opts)
73+
options, err := parseTableOptions(opts)
74+
if err != nil {
75+
return err
76+
}
6677
// Coordinate conversion, convert C1:B3 to 2,0,1,2.
6778
coordinates, err := rangeRefToCoordinates(rangeRef)
6879
if err != nil {
@@ -147,6 +158,29 @@ func (f *File) setTableHeader(sheet string, x1, y1, x2 int) ([]*xlsxTableColumn,
147158
return tableColumns, nil
148159
}
149160

161+
// checkSheetName check whether there are illegal characters in the table name.
162+
// Verify that the name:
163+
// 1. Starts with a letter or underscore (_)
164+
// 2. Doesn't include a space or character that isn't allowed
165+
func checkTableName(name string) error {
166+
if utf8.RuneCountInString(name) > MaxFieldLength {
167+
return ErrTableNameLength
168+
}
169+
for i, c := range name {
170+
if string(c) == "_" {
171+
continue
172+
}
173+
if unicode.IsLetter(c) {
174+
continue
175+
}
176+
if i > 0 && unicode.IsDigit(c) {
177+
continue
178+
}
179+
return newInvalidTableNameError(name)
180+
}
181+
return nil
182+
}
183+
150184
// addTable provides a function to add table by given worksheet name,
151185
// range reference and format set.
152186
func (f *File) addTable(sheet, tableXML string, x1, y1, x2, y2, i int, opts *TableOptions) error {

table_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package excelize
33
import (
44
"fmt"
55
"path/filepath"
6+
"strings"
67
"testing"
78

89
"github.com/stretchr/testify/assert"
@@ -37,6 +38,24 @@ func TestAddTable(t *testing.T) {
3738
f = NewFile()
3839
assert.EqualError(t, f.addTable("sheet1", "", 0, 0, 0, 0, 0, nil), "invalid cell reference [0, 0]")
3940
assert.EqualError(t, f.addTable("sheet1", "", 1, 1, 0, 0, 0, nil), "invalid cell reference [0, 0]")
41+
// Test add table with invalid table name
42+
for _, cases := range []struct {
43+
name string
44+
err error
45+
}{
46+
{name: "1Table", err: newInvalidTableNameError("1Table")},
47+
{name: "-Table", err: newInvalidTableNameError("-Table")},
48+
{name: "'Table", err: newInvalidTableNameError("'Table")},
49+
{name: "Table 1", err: newInvalidTableNameError("Table 1")},
50+
{name: "A&B", err: newInvalidTableNameError("A&B")},
51+
{name: "_1Table'", err: newInvalidTableNameError("_1Table'")},
52+
{name: "\u0f5f\u0fb3\u0f0b\u0f21", err: newInvalidTableNameError("\u0f5f\u0fb3\u0f0b\u0f21")},
53+
{name: strings.Repeat("c", MaxFieldLength+1), err: ErrTableNameLength},
54+
} {
55+
assert.EqualError(t, f.AddTable("Sheet1", "A1:B2", &TableOptions{
56+
Name: cases.name,
57+
}), cases.err.Error())
58+
}
4059
}
4160

4261
func TestSetTableHeader(t *testing.T) {

xmlWorksheet.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -766,15 +766,15 @@ type decodeX14ConditionalFormatting struct {
766766

767767
// decodeX14CfRule directly maps the cfRule element.
768768
type decodeX14CfRule struct {
769-
XNLName xml.Name `xml:"cfRule"`
769+
XMLName xml.Name `xml:"cfRule"`
770770
Type string `xml:"type,attr,omitempty"`
771771
ID string `xml:"id,attr,omitempty"`
772772
DataBar *decodeX14DataBar `xml:"dataBar"`
773773
}
774774

775775
// decodeX14DataBar directly maps the dataBar element.
776776
type decodeX14DataBar struct {
777-
XNLName xml.Name `xml:"dataBar"`
777+
XMLName xml.Name `xml:"dataBar"`
778778
MaxLength int `xml:"maxLength,attr"`
779779
MinLength int `xml:"minLength,attr"`
780780
Border bool `xml:"border,attr,omitempty"`

0 commit comments

Comments
 (0)