Compare commits
23 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
b19e5940b8 | |
![]() |
0e0e2dadcf | |
![]() |
7e614c5104 | |
![]() |
a45d47d57c | |
|
b936343814 | |
![]() |
e9efc47316 | |
|
af422e1700 | |
![]() |
4b4d4df76b | |
|
caf22e4974 | |
|
3f6ecffcca | |
|
9934bf5c86 | |
|
5ef4a360c1 | |
|
8e0490927e | |
|
b53bad3541 | |
|
3ca60f8d23 | |
![]() |
c93618856a | |
|
5f446f25f0 | |
![]() |
30d3561d0e | |
![]() |
d2be5cdf8e | |
![]() |
b7375bc6d4 | |
|
0d5d1c53b2 | |
|
af190c7fdc | |
![]() |
d1937a0cde |
|
@ -1,44 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If you are reporting a new issue, make sure that we do not have any duplicates
|
|
||||||
already open. You can ensure this by searching the issue list for this
|
|
||||||
repository. If there is a duplicate, please close your issue and add a comment
|
|
||||||
to the existing issue instead.
|
|
||||||
|
|
||||||
Use the commands below to provide key information from your environment:
|
|
||||||
You do NOT have to include this information if this is a FEATURE REQUEST
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Briefly describe the problem you are having in a few paragraphs.
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Steps to reproduce the issue:**
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
|
|
||||||
**Describe the results you received:**
|
|
||||||
|
|
||||||
**Describe the results you expected:**
|
|
||||||
|
|
||||||
**Output of `go version`:**
|
|
||||||
|
|
||||||
```text
|
|
||||||
(paste your output here)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Excelize version or commit ID:**
|
|
||||||
|
|
||||||
```text
|
|
||||||
(paste here)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Environment details (OS, Microsoft Excel™ version, physical, etc.):**
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
name: Bug report
|
||||||
|
description: Create a report to help us improve
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
If you are reporting a new issue, make sure that we do not have any duplicates already open. You can ensure this by searching the issue list for this repository. If there is a duplicate, please close your issue and add a comment to the existing issue instead.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Briefly describe the problem you are having in a few paragraphs.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction-steps
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce the issue
|
||||||
|
description: Explain how to cause the issue in the provided reproduction.
|
||||||
|
placeholder: |
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: received
|
||||||
|
attributes:
|
||||||
|
label: Describe the results you received
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Describe the results you expected
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: go-version
|
||||||
|
attributes:
|
||||||
|
label: Go version
|
||||||
|
description: |
|
||||||
|
Output of `go version`:
|
||||||
|
placeholder: e.g. 1.23.4
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: excelize-version
|
||||||
|
attributes:
|
||||||
|
label: Excelize version or commit ID
|
||||||
|
description: |
|
||||||
|
Which version of Excelize are you using?
|
||||||
|
placeholder: e.g. 2.9.0
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: env
|
||||||
|
attributes:
|
||||||
|
label: Environment
|
||||||
|
description: Environment details (OS, Microsoft Excel™ version, physical, etc.)
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: checkboxes
|
||||||
|
id: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Validations
|
||||||
|
description: Before submitting the issue, please make sure you do the following
|
||||||
|
options:
|
||||||
|
- label: Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
|
||||||
|
required: true
|
||||||
|
- label: The provided reproduction is a minimal reproducible example of the bug.
|
||||||
|
required: true
|
|
@ -1,44 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
If you are reporting a new issue, make sure that we do not have any duplicates
|
|
||||||
already open. You can ensure this by searching the issue list for this
|
|
||||||
repository. If there is a duplicate, please close your issue and add a comment
|
|
||||||
to the existing issue instead.
|
|
||||||
|
|
||||||
Use the commands below to provide key information from your environment:
|
|
||||||
You do NOT have to include this information if this is a FEATURE REQUEST
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Briefly describe the problem you are having in a few paragraphs.
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Steps to reproduce the issue:**
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
|
|
||||||
**Describe the results you received:**
|
|
||||||
|
|
||||||
**Describe the results you expected:**
|
|
||||||
|
|
||||||
**Output of `go version`:**
|
|
||||||
|
|
||||||
```text
|
|
||||||
(paste your output here)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Excelize version or commit ID:**
|
|
||||||
|
|
||||||
```text
|
|
||||||
(paste here)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Environment details (OS, Microsoft Excel™ version, physical, etc.):**
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: Feature request
|
||||||
|
description: Suggest an idea for this project
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
If you are reporting a new issue, make sure that we do not have any duplicates already open. You can ensure this by searching the issue list for this repository. If there is a duplicate, please close your issue and add a comment to the existing issue instead.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Describe the feature that you would like added
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: additional-context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Any other context or screenshots about the feature request here?
|
||||||
|
|
||||||
|
- type: checkboxes
|
||||||
|
id: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Validations
|
||||||
|
description: Before submitting the issue, please make sure you do the following
|
||||||
|
options:
|
||||||
|
- label: Check that there isn't already an issue that requests the same feature to avoid creating a duplicate.
|
||||||
|
required: true
|
|
@ -11,7 +11,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
|
@ -5,8 +5,8 @@ jobs:
|
||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [1.18.x, 1.19.x, 1.20.x, '>=1.21.1', 1.22.x, 1.23.x]
|
go-version: [1.20.x, '>=1.21.1', 1.22.x, 1.23.x]
|
||||||
os: [ubuntu-latest, macos-13, windows-latest]
|
os: [ubuntu-24.04, macos-13, windows-latest]
|
||||||
targetplatform: [x86, x64]
|
targetplatform: [x86, x64]
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
@ -32,10 +32,10 @@ jobs:
|
||||||
run: env GO111MODULE=on go test -v -timeout 30m -race ./... -coverprofile='coverage.txt' -covermode=atomic
|
run: env GO111MODULE=on go test -v -timeout 30m -race ./... -coverprofile='coverage.txt' -covermode=atomic
|
||||||
|
|
||||||
- name: Codecov
|
- name: Codecov
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v5
|
||||||
env:
|
env:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
with:
|
with:
|
||||||
file: coverage.txt
|
files: coverage.txt
|
||||||
flags: unittests
|
flags: unittests
|
||||||
name: codecov-umbrella
|
name: codecov-umbrella
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2016-2024 The excelize Authors.
|
Copyright (c) 2016-2025 The excelize Authors.
|
||||||
Copyright (c) 2011-2017 Geoffrey J. Teale
|
Copyright (c) 2011-2017 Geoffrey J. Teale
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.18 or later. There are some [incompatible changes](https://github.com/golang/go/issues/61881) in the Go 1.21.0, the Excelize library can not working with that version normally, if you are using the Go 1.21.x, please upgrade to the Go 1.21.1 and later version. The full docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) and [docs reference](https://xuri.me/excelize/).
|
Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and writing spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports complex components by high compatibility, and provided streaming API for generating or reading data from a worksheet with huge amounts of data. This library needs Go version 1.20 or later. There are some [incompatible changes](https://github.com/golang/go/issues/61881) in the Go 1.21.0, the Excelize library can not working with that version normally, if you are using the Go 1.21.x, please upgrade to the Go 1.21.1 and later version. The full docs can be seen using go's built-in documentation tool, or online at [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) and [docs reference](https://xuri.me/excelize/).
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
|
|
||||||
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写函数,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.18 或更高版本,请注意,Go 1.21.0 中存在[不兼容的更改](https://github.com/golang/go/issues/61881),导致 Excelize 基础库无法在该版本上正常工作,如果您使用的是 Go 1.21.x,请升级到 Go 1.21.1 及更高版本。完整的使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。
|
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写函数,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.20 或更高版本,请注意,Go 1.21.0 中存在[不兼容的更改](https://github.com/golang/go/issues/61881),导致 Excelize 基础库无法在该版本上正常工作,如果您使用的是 Go 1.21.x,请升级到 Go 1.21.1 及更高版本。完整的使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -969,7 +969,7 @@ func (f *File) adjustDataValidations(ws *xlsxWorksheet, sheet string, dir adjust
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if worksheet.DataValidations == nil {
|
if worksheet.DataValidations == nil {
|
||||||
return nil
|
continue
|
||||||
}
|
}
|
||||||
for i := 0; i < len(worksheet.DataValidations.DataValidation); i++ {
|
for i := 0; i < len(worksheet.DataValidations.DataValidation); i++ {
|
||||||
dv := worksheet.DataValidations.DataValidation[i]
|
dv := worksheet.DataValidations.DataValidation[i]
|
||||||
|
|
|
@ -1170,6 +1170,25 @@ func TestAdjustDataValidations(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, formula, dvs[0].Formula1)
|
assert.Equal(t, formula, dvs[0].Formula1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("no_data_validations_on_first_sheet", func(t *testing.T) {
|
||||||
|
f := NewFile()
|
||||||
|
|
||||||
|
// Add Sheet2 and set a data validation
|
||||||
|
_, err = f.NewSheet("Sheet2")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
dv := NewDataValidation(true)
|
||||||
|
dv.Sqref = "C5:D6"
|
||||||
|
assert.NoError(t, f.AddDataValidation("Sheet2", dv))
|
||||||
|
|
||||||
|
// Adjust Sheet2 by removing a column
|
||||||
|
assert.NoError(t, f.RemoveCol("Sheet2", "A"))
|
||||||
|
|
||||||
|
// Verify that data validations on Sheet2 are adjusted correctly
|
||||||
|
dvs, err = f.GetDataValidations("Sheet2")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "B5:C6", dvs[0].Sqref) // Adjusted range
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdjustDrawings(t *testing.T) {
|
func TestAdjustDrawings(t *testing.T) {
|
||||||
|
|
11
calc.go
11
calc.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -13629,7 +13629,9 @@ func (fn *formulaFuncs) DBCS(argsList *list.List) formulaArg {
|
||||||
if arg.Type == ArgError {
|
if arg.Type == ArgError {
|
||||||
return arg
|
return arg
|
||||||
}
|
}
|
||||||
if fn.f.options.CultureInfo == CultureNameZhCN {
|
if fn.f.options.CultureInfo == CultureNameJaJP ||
|
||||||
|
fn.f.options.CultureInfo == CultureNameZhCN ||
|
||||||
|
fn.f.options.CultureInfo == CultureNameZhTW {
|
||||||
var chars []string
|
var chars []string
|
||||||
for _, r := range arg.Value() {
|
for _, r := range arg.Value() {
|
||||||
code := r
|
code := r
|
||||||
|
@ -16378,7 +16380,10 @@ func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg {
|
||||||
symbol := map[CultureName]string{
|
symbol := map[CultureName]string{
|
||||||
CultureNameUnknown: "$",
|
CultureNameUnknown: "$",
|
||||||
CultureNameEnUS: "$",
|
CultureNameEnUS: "$",
|
||||||
|
CultureNameJaJP: "¥",
|
||||||
|
CultureNameKoKR: "\u20a9",
|
||||||
CultureNameZhCN: "¥",
|
CultureNameZhCN: "¥",
|
||||||
|
CultureNameZhTW: "NT$",
|
||||||
}[fn.f.options.CultureInfo]
|
}[fn.f.options.CultureInfo]
|
||||||
numFmtCode := fmt.Sprintf("%s#,##0%s%s;(%s#,##0%s%s)",
|
numFmtCode := fmt.Sprintf("%s#,##0%s%s;(%s#,##0%s%s)",
|
||||||
symbol, dot, strings.Repeat("0", decimals), symbol, dot, strings.Repeat("0", decimals))
|
symbol, dot, strings.Repeat("0", decimals), symbol, dot, strings.Repeat("0", decimals))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
47
cell.go
47
cell.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -207,15 +207,15 @@ func (f *File) setCellIntFunc(sheet, cell string, value interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case int:
|
case int:
|
||||||
err = f.SetCellInt(sheet, cell, v)
|
err = f.SetCellInt(sheet, cell, int64(v))
|
||||||
case int8:
|
case int8:
|
||||||
err = f.SetCellInt(sheet, cell, int(v))
|
err = f.SetCellInt(sheet, cell, int64(v))
|
||||||
case int16:
|
case int16:
|
||||||
err = f.SetCellInt(sheet, cell, int(v))
|
err = f.SetCellInt(sheet, cell, int64(v))
|
||||||
case int32:
|
case int32:
|
||||||
err = f.SetCellInt(sheet, cell, int(v))
|
err = f.SetCellInt(sheet, cell, int64(v))
|
||||||
case int64:
|
case int64:
|
||||||
err = f.SetCellInt(sheet, cell, int(v))
|
err = f.SetCellInt(sheet, cell, v)
|
||||||
case uint:
|
case uint:
|
||||||
err = f.SetCellUint(sheet, cell, uint64(v))
|
err = f.SetCellUint(sheet, cell, uint64(v))
|
||||||
case uint8:
|
case uint8:
|
||||||
|
@ -288,7 +288,7 @@ func setCellDuration(value time.Duration) (t string, v string) {
|
||||||
|
|
||||||
// SetCellInt provides a function to set int type value of a cell by given
|
// SetCellInt provides a function to set int type value of a cell by given
|
||||||
// worksheet name, cell reference and cell value.
|
// worksheet name, cell reference and cell value.
|
||||||
func (f *File) SetCellInt(sheet, cell string, value int) error {
|
func (f *File) SetCellInt(sheet, cell string, value int64) error {
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -309,8 +309,8 @@ func (f *File) SetCellInt(sheet, cell string, value int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setCellInt prepares cell type and string type cell value by a given integer.
|
// setCellInt prepares cell type and string type cell value by a given integer.
|
||||||
func setCellInt(value int) (t string, v string) {
|
func setCellInt(value int64) (t string, v string) {
|
||||||
v = strconv.Itoa(value)
|
v = strconv.FormatInt(value, 10)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,7 +1101,7 @@ func getCellRichText(si *xlsxSI) (runs []RichTextRun) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCellRichText provides a function to get rich text of cell by given
|
// GetCellRichText provides a function to get rich text of cell by given
|
||||||
// worksheet.
|
// worksheet and cell reference.
|
||||||
func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err error) {
|
func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err error) {
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1164,7 +1164,7 @@ func newRpr(fnt *Font) *xlsxRPr {
|
||||||
|
|
||||||
// newFont create font format by given run properties for the rich text.
|
// newFont create font format by given run properties for the rich text.
|
||||||
func newFont(rPr *xlsxRPr) *Font {
|
func newFont(rPr *xlsxRPr) *Font {
|
||||||
font := Font{Underline: "none"}
|
var font Font
|
||||||
font.Bold = rPr.B != nil
|
font.Bold = rPr.B != nil
|
||||||
font.Italic = rPr.I != nil
|
font.Italic = rPr.I != nil
|
||||||
if rPr.U != nil {
|
if rPr.U != nil {
|
||||||
|
@ -1179,6 +1179,9 @@ func newFont(rPr *xlsxRPr) *Font {
|
||||||
if rPr.Sz != nil && rPr.Sz.Val != nil {
|
if rPr.Sz != nil && rPr.Sz.Val != nil {
|
||||||
font.Size = *rPr.Sz.Val
|
font.Size = *rPr.Sz.Val
|
||||||
}
|
}
|
||||||
|
if rPr.VertAlign != nil && rPr.VertAlign.Val != nil {
|
||||||
|
font.VertAlign = *rPr.VertAlign.Val
|
||||||
|
}
|
||||||
font.Strike = rPr.Strike != nil
|
font.Strike = rPr.Strike != nil
|
||||||
if rPr.Color != nil {
|
if rPr.Color != nil {
|
||||||
font.Color = strings.TrimPrefix(rPr.Color.RGB, "FF")
|
font.Color = strings.TrimPrefix(rPr.Color.RGB, "FF")
|
||||||
|
@ -1214,8 +1217,8 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCellRichText provides a function to set cell with rich text by given
|
// SetCellRichText provides a function to set cell with rich text by given
|
||||||
// worksheet. For example, set rich text on the A1 cell of the worksheet named
|
// worksheet name, cell reference and rich text runs. For example, set rich text
|
||||||
// Sheet1:
|
// on the A1 cell of the worksheet named Sheet1:
|
||||||
//
|
//
|
||||||
// package main
|
// package main
|
||||||
//
|
//
|
||||||
|
@ -1245,7 +1248,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
|
||||||
// Text: "bold",
|
// Text: "bold",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Bold: true,
|
// Bold: true,
|
||||||
// Color: "2354e8",
|
// Color: "2354E8",
|
||||||
// Family: "Times New Roman",
|
// Family: "Times New Roman",
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
@ -1259,7 +1262,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
|
||||||
// Text: "italic ",
|
// Text: "italic ",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Bold: true,
|
// Bold: true,
|
||||||
// Color: "e83723",
|
// Color: "E83723",
|
||||||
// Italic: true,
|
// Italic: true,
|
||||||
// Family: "Times New Roman",
|
// Family: "Times New Roman",
|
||||||
// },
|
// },
|
||||||
|
@ -1268,7 +1271,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
|
||||||
// Text: "text with color and font-family,",
|
// Text: "text with color and font-family,",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Bold: true,
|
// Bold: true,
|
||||||
// Color: "2354e8",
|
// Color: "2354E8",
|
||||||
// Family: "Times New Roman",
|
// Family: "Times New Roman",
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
@ -1276,20 +1279,20 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
|
||||||
// Text: "\r\nlarge text with ",
|
// Text: "\r\nlarge text with ",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Size: 14,
|
// Size: 14,
|
||||||
// Color: "ad23e8",
|
// Color: "AD23E8",
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// Text: "strike",
|
// Text: "strike",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Color: "e89923",
|
// Color: "E89923",
|
||||||
// Strike: true,
|
// Strike: true,
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// Text: " superscript",
|
// Text: " superscript",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Color: "dbc21f",
|
// Color: "DBC21F",
|
||||||
// VertAlign: "superscript",
|
// VertAlign: "superscript",
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
@ -1297,14 +1300,14 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
|
||||||
// Text: " and ",
|
// Text: " and ",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Size: 14,
|
// Size: 14,
|
||||||
// Color: "ad23e8",
|
// Color: "AD23E8",
|
||||||
// VertAlign: "baseline",
|
// VertAlign: "baseline",
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// Text: "underline",
|
// Text: "underline",
|
||||||
// Font: &excelize.Font{
|
// Font: &excelize.Font{
|
||||||
// Color: "23e833",
|
// Color: "23E833",
|
||||||
// Underline: "single",
|
// Underline: "single",
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
|
|
46
cell_test.go
46
cell_test.go
|
@ -856,7 +856,7 @@ func TestSetCellRichText(t *testing.T) {
|
||||||
Text: "bold",
|
Text: "bold",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Bold: true,
|
Bold: true,
|
||||||
Color: "2354e8",
|
Color: "2354E8",
|
||||||
ColorIndexed: 0,
|
ColorIndexed: 0,
|
||||||
Family: "Times New Roman",
|
Family: "Times New Roman",
|
||||||
},
|
},
|
||||||
|
@ -871,7 +871,7 @@ func TestSetCellRichText(t *testing.T) {
|
||||||
Text: "italic ",
|
Text: "italic ",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Bold: true,
|
Bold: true,
|
||||||
Color: "e83723",
|
Color: "E83723",
|
||||||
Italic: true,
|
Italic: true,
|
||||||
Family: "Times New Roman",
|
Family: "Times New Roman",
|
||||||
},
|
},
|
||||||
|
@ -880,7 +880,7 @@ func TestSetCellRichText(t *testing.T) {
|
||||||
Text: "text with color and font-family, ",
|
Text: "text with color and font-family, ",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Bold: true,
|
Bold: true,
|
||||||
Color: "2354e8",
|
Color: "2354E8",
|
||||||
Family: "Times New Roman",
|
Family: "Times New Roman",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -888,20 +888,20 @@ func TestSetCellRichText(t *testing.T) {
|
||||||
Text: "\r\nlarge text with ",
|
Text: "\r\nlarge text with ",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Size: 14,
|
Size: 14,
|
||||||
Color: "ad23e8",
|
Color: "AD23E8",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Text: "strike",
|
Text: "strike",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Color: "e89923",
|
Color: "E89923",
|
||||||
Strike: true,
|
Strike: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Text: " superscript",
|
Text: " superscript",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Color: "dbc21f",
|
Color: "DBC21F",
|
||||||
VertAlign: "superscript",
|
VertAlign: "superscript",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -909,14 +909,14 @@ func TestSetCellRichText(t *testing.T) {
|
||||||
Text: " and ",
|
Text: " and ",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Size: 14,
|
Size: 14,
|
||||||
Color: "ad23e8",
|
Color: "AD23E8",
|
||||||
VertAlign: "BASELINE",
|
VertAlign: "baseline",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Text: "underline",
|
Text: "underline",
|
||||||
Font: &Font{
|
Font: &Font{
|
||||||
Color: "23e833",
|
Color: "23E833",
|
||||||
Underline: "single",
|
Underline: "single",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -937,6 +937,11 @@ func TestSetCellRichText(t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
|
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
|
||||||
|
|
||||||
|
runs, err := f.GetCellRichText("Sheet1", "A1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, richTextRun, runs)
|
||||||
|
|
||||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellRichText.xlsx")))
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellRichText.xlsx")))
|
||||||
// Test set cell rich text on not exists worksheet
|
// Test set cell rich text on not exists worksheet
|
||||||
assert.EqualError(t, f.SetCellRichText("SheetN", "A1", richTextRun), "sheet SheetN does not exist")
|
assert.EqualError(t, f.SetCellRichText("SheetN", "A1", richTextRun), "sheet SheetN does not exist")
|
||||||
|
@ -1153,6 +1158,29 @@ func TestSharedStringsError(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetCellIntFunc(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
val interface{}
|
||||||
|
target string
|
||||||
|
}{
|
||||||
|
{val: 128, target: "128"},
|
||||||
|
{val: int8(-128), target: "-128"},
|
||||||
|
{val: int16(-32768), target: "-32768"},
|
||||||
|
{val: int32(-2147483648), target: "-2147483648"},
|
||||||
|
{val: int64(-9223372036854775808), target: "-9223372036854775808"},
|
||||||
|
{val: uint(128), target: "128"},
|
||||||
|
{val: uint8(255), target: "255"},
|
||||||
|
{val: uint16(65535), target: "65535"},
|
||||||
|
{val: uint32(4294967295), target: "4294967295"},
|
||||||
|
{val: uint64(18446744073709551615), target: "18446744073709551615"},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
cell := &xlsxC{}
|
||||||
|
setCellIntFunc(cell, c.val)
|
||||||
|
assert.Equal(t, c.target, cell.V)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSIString(t *testing.T) {
|
func TestSIString(t *testing.T) {
|
||||||
assert.Empty(t, xlsxSI{}.String())
|
assert.Empty(t, xlsxSI{}.String())
|
||||||
}
|
}
|
||||||
|
|
71
chart.go
71
chart.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -486,6 +486,42 @@ var (
|
||||||
Line: "standard",
|
Line: "standard",
|
||||||
Line3D: "standard",
|
Line3D: "standard",
|
||||||
}
|
}
|
||||||
|
barColChartTypes = []ChartType{
|
||||||
|
Bar,
|
||||||
|
BarStacked,
|
||||||
|
BarPercentStacked,
|
||||||
|
Bar3DClustered,
|
||||||
|
Bar3DStacked,
|
||||||
|
Bar3DPercentStacked,
|
||||||
|
Bar3DConeClustered,
|
||||||
|
Bar3DConeStacked,
|
||||||
|
Bar3DConePercentStacked,
|
||||||
|
Bar3DPyramidClustered,
|
||||||
|
Bar3DPyramidStacked,
|
||||||
|
Bar3DPyramidPercentStacked,
|
||||||
|
Bar3DCylinderClustered,
|
||||||
|
Bar3DCylinderStacked,
|
||||||
|
Bar3DCylinderPercentStacked,
|
||||||
|
Col,
|
||||||
|
ColStacked,
|
||||||
|
ColPercentStacked,
|
||||||
|
Col3D,
|
||||||
|
Col3DClustered,
|
||||||
|
Col3DStacked,
|
||||||
|
Col3DPercentStacked,
|
||||||
|
Col3DCone,
|
||||||
|
Col3DConeStacked,
|
||||||
|
Col3DConeClustered,
|
||||||
|
Col3DConePercentStacked,
|
||||||
|
Col3DPyramid,
|
||||||
|
Col3DPyramidClustered,
|
||||||
|
Col3DPyramidStacked,
|
||||||
|
Col3DPyramidPercentStacked,
|
||||||
|
Col3DCylinder,
|
||||||
|
Col3DCylinderClustered,
|
||||||
|
Col3DCylinderStacked,
|
||||||
|
Col3DCylinderPercentStacked,
|
||||||
|
}
|
||||||
orientation = map[bool]string{
|
orientation = map[bool]string{
|
||||||
true: "maxMin",
|
true: "maxMin",
|
||||||
false: "minMax",
|
false: "minMax",
|
||||||
|
@ -712,6 +748,7 @@ func (opts *Chart) parseTitle() {
|
||||||
// Fill
|
// Fill
|
||||||
// Line
|
// Line
|
||||||
// Marker
|
// Marker
|
||||||
|
// DataLabel
|
||||||
// DataLabelPosition
|
// DataLabelPosition
|
||||||
//
|
//
|
||||||
// Name: Set the name for the series. The name is displayed in the chart legend
|
// Name: Set the name for the series. The name is displayed in the chart legend
|
||||||
|
@ -755,6 +792,8 @@ func (opts *Chart) parseTitle() {
|
||||||
// x
|
// x
|
||||||
// auto
|
// auto
|
||||||
//
|
//
|
||||||
|
// DataLabel: This sets the format of the chart series data label.
|
||||||
|
//
|
||||||
// DataLabelPosition: This sets the position of the chart series data label.
|
// DataLabelPosition: This sets the position of the chart series data label.
|
||||||
//
|
//
|
||||||
// Set properties of the chart legend. The options that can be set are:
|
// Set properties of the chart legend. The options that can be set are:
|
||||||
|
@ -850,6 +889,7 @@ func (opts *Chart) parseTitle() {
|
||||||
// ReverseOrder
|
// ReverseOrder
|
||||||
// Maximum
|
// Maximum
|
||||||
// Minimum
|
// Minimum
|
||||||
|
// Alignment
|
||||||
// Font
|
// Font
|
||||||
// NumFmt
|
// NumFmt
|
||||||
// Title
|
// Title
|
||||||
|
@ -864,6 +904,7 @@ func (opts *Chart) parseTitle() {
|
||||||
// ReverseOrder
|
// ReverseOrder
|
||||||
// Maximum
|
// Maximum
|
||||||
// Minimum
|
// Minimum
|
||||||
|
// Alignment
|
||||||
// Font
|
// Font
|
||||||
// LogBase
|
// LogBase
|
||||||
// NumFmt
|
// NumFmt
|
||||||
|
@ -896,6 +937,24 @@ func (opts *Chart) parseTitle() {
|
||||||
// Minimum: Specifies that the fixed minimum, 0 is auto. The 'Minimum' property
|
// Minimum: Specifies that the fixed minimum, 0 is auto. The 'Minimum' property
|
||||||
// is optional. The default value is auto.
|
// is optional. The default value is auto.
|
||||||
//
|
//
|
||||||
|
// Alignment: Specifies that the alignment of the horizontal and vertical axis.
|
||||||
|
// The properties of alignment that can be set are:
|
||||||
|
//
|
||||||
|
// TextRotation
|
||||||
|
// Vertical
|
||||||
|
//
|
||||||
|
// The value of 'TextRotation' that can be set from -90 to 90.
|
||||||
|
//
|
||||||
|
// The value of 'Vertical' that can be set are:
|
||||||
|
//
|
||||||
|
// horz
|
||||||
|
// vert
|
||||||
|
// vert270
|
||||||
|
// wordArtVert
|
||||||
|
// eaVert
|
||||||
|
// mongolianVert
|
||||||
|
// wordArtVertRtl
|
||||||
|
//
|
||||||
// Font: Specifies that the font of the horizontal and vertical axis. The
|
// Font: Specifies that the font of the horizontal and vertical axis. The
|
||||||
// properties of font that can be set are:
|
// properties of font that can be set are:
|
||||||
//
|
//
|
||||||
|
@ -929,6 +988,14 @@ func (opts *Chart) parseTitle() {
|
||||||
// 'HoleSize' property. The 'HoleSize' property is optional. The default width
|
// 'HoleSize' property. The 'HoleSize' property is optional. The default width
|
||||||
// is 75, and the value should be great than 0 and less or equal than 90.
|
// is 75, and the value should be great than 0 and less or equal than 90.
|
||||||
//
|
//
|
||||||
|
// Set the gap with of the column and bar series chart by 'GapWidth' property.
|
||||||
|
// The 'GapWidth' property is optional. The default width is 150, and the value
|
||||||
|
// should be great or equal than 0 and less or equal than 500.
|
||||||
|
//
|
||||||
|
// Set series overlap of the column and bar series chart by 'Overlap' property.
|
||||||
|
// The 'Overlap' property is optional. The default width is 0, and the value
|
||||||
|
// should be great or equal than -100 and less or equal than 100.
|
||||||
|
//
|
||||||
// combo: Specifies the create a chart that combines two or more chart types in
|
// combo: Specifies the create a chart that combines two or more chart types in
|
||||||
// a single chart. For example, create a clustered column - line chart with
|
// a single chart. For example, create a clustered column - line chart with
|
||||||
// data Sheet1!$E$1:$L$15:
|
// data Sheet1!$E$1:$L$15:
|
||||||
|
|
|
@ -124,6 +124,11 @@ func TestDeleteDrawing(t *testing.T) {
|
||||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||||
f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
|
f, err = OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
f.Drawings.Store(path, &xlsxWsDr{OneCellAnchor: []*xdrCellAnchor{{
|
||||||
|
GraphicFrame: string(MacintoshCyrillicCharset),
|
||||||
|
}}})
|
||||||
|
_, err = f.deleteDrawing(0, 0, path, "Chart")
|
||||||
|
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||||
f.Drawings.Store(path, &xlsxWsDr{TwoCellAnchor: []*xdrCellAnchor{{
|
f.Drawings.Store(path, &xlsxWsDr{TwoCellAnchor: []*xdrCellAnchor{{
|
||||||
GraphicFrame: string(MacintoshCyrillicCharset),
|
GraphicFrame: string(MacintoshCyrillicCharset),
|
||||||
}}})
|
}}})
|
||||||
|
@ -215,10 +220,10 @@ func TestAddChart(t *testing.T) {
|
||||||
opts *Chart
|
opts *Chart
|
||||||
}{
|
}{
|
||||||
{sheetName: "Sheet1", cell: "P1", opts: &Chart{Type: Col, Series: series, Format: format, Legend: ChartLegend{Position: "none", ShowLegendKey: true}, Title: []RichTextRun{{Text: "2D Column Chart"}}, PlotArea: plotArea, Border: ChartLine{Type: ChartLineNone}, ShowBlanksAs: "zero", XAxis: ChartAxis{Font: Font{Bold: true, Italic: true, Underline: "dbl", Family: "Times New Roman", Size: 15, Strike: true, Color: "000000"}, Title: []RichTextRun{{Text: "Primary Horizontal Axis Title"}}}, YAxis: ChartAxis{Font: Font{Bold: false, Italic: false, Underline: "sng", Color: "777777"}, Title: []RichTextRun{{Text: "Primary Vertical Axis Title", Font: &Font{Color: "777777", Bold: true, Italic: true, Size: 12}}}}}},
|
{sheetName: "Sheet1", cell: "P1", opts: &Chart{Type: Col, Series: series, Format: format, Legend: ChartLegend{Position: "none", ShowLegendKey: true}, Title: []RichTextRun{{Text: "2D Column Chart"}}, PlotArea: plotArea, Border: ChartLine{Type: ChartLineNone}, ShowBlanksAs: "zero", XAxis: ChartAxis{Font: Font{Bold: true, Italic: true, Underline: "dbl", Family: "Times New Roman", Size: 15, Strike: true, Color: "000000"}, Title: []RichTextRun{{Text: "Primary Horizontal Axis Title"}}}, YAxis: ChartAxis{Font: Font{Bold: false, Italic: false, Underline: "sng", Color: "777777"}, Title: []RichTextRun{{Text: "Primary Vertical Axis Title", Font: &Font{Color: "777777", Bold: true, Italic: true, Size: 12}}}}}},
|
||||||
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Pattern: 1}, Border: ChartLine{Type: ChartLineAutomatic}, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Pattern: 1}, Border: ChartLine{Type: ChartLineAutomatic}, ShowBlanksAs: "zero", GapWidth: uintPtr(10), Overlap: intPtr(100)}},
|
||||||
{sheetName: "Sheet1", cell: "P16", opts: &Chart{Type: ColPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "100% Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Color: []string{"EEEEEE"}, Pattern: 1}, Border: ChartLine{Type: ChartLineSolid, Width: 2}, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "P16", opts: &Chart{Type: ColPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "100% Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Color: []string{"EEEEEE"}, Pattern: 1}, Border: ChartLine{Type: ChartLineSolid, Width: 2}, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "wordArtVertRtl", TextRotation: 0}}}},
|
||||||
{sheetName: "Sheet1", cell: "X16", opts: &Chart{Type: Col3DClustered, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: []RichTextRun{{Text: "3D Clustered Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "X16", opts: &Chart{Type: Col3DClustered, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: []RichTextRun{{Text: "3D Clustered Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
{sheetName: "Sheet1", cell: "P30", opts: &Chart{Type: Col3DStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "P30", opts: &Chart{Type: Col3DStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "vert", TextRotation: 0}}}},
|
||||||
{sheetName: "Sheet1", cell: "X30", opts: &Chart{Type: Col3DPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D 100% Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "X30", opts: &Chart{Type: Col3DPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D 100% Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
{sheetName: "Sheet1", cell: "X45", opts: &Chart{Type: Radar, Series: series, Format: format, Legend: ChartLegend{Position: "top_right", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Radar Chart"}}, PlotArea: plotArea, ShowBlanksAs: "span"}},
|
{sheetName: "Sheet1", cell: "X45", opts: &Chart{Type: Radar, Series: series, Format: format, Legend: ChartLegend{Position: "top_right", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Radar Chart"}}, PlotArea: plotArea, ShowBlanksAs: "span"}},
|
||||||
{sheetName: "Sheet1", cell: "AF1", opts: &Chart{Type: Col3DConeStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cone Stacked Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "AF1", opts: &Chart{Type: Col3DConeStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cone Stacked Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
|
@ -233,7 +238,7 @@ func TestAddChart(t *testing.T) {
|
||||||
{sheetName: "Sheet1", cell: "AV16", opts: &Chart{Type: Col3DCylinderClustered, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cylinder Clustered Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "AV16", opts: &Chart{Type: Col3DCylinderClustered, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cylinder Clustered Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
{sheetName: "Sheet1", cell: "AV30", opts: &Chart{Type: Col3DCylinderPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cylinder Percent Stacked Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "AV30", opts: &Chart{Type: Col3DCylinderPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cylinder Percent Stacked Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
{sheetName: "Sheet1", cell: "AV45", opts: &Chart{Type: Col3DCylinder, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cylinder Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "AV45", opts: &Chart{Type: Col3DCylinder, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Cylinder Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
{sheetName: "Sheet1", cell: "P45", opts: &Chart{Type: Col3D, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet1", cell: "P45", opts: &Chart{Type: Col3D, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "vert270", TextRotation: 0}}}},
|
||||||
{sheetName: "Sheet2", cell: "P1", opts: &Chart{Type: Line3D, Series: series2, Format: format, Legend: ChartLegend{Position: "top", ShowLegendKey: false}, Title: []RichTextRun{{Text: "3D Line Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, TickLabelSkip: 1, NumFmt: ChartNumFmt{CustomNumFmt: "General"}}, YAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, MajorUnit: 1, NumFmt: ChartNumFmt{CustomNumFmt: "General"}}}},
|
{sheetName: "Sheet2", cell: "P1", opts: &Chart{Type: Line3D, Series: series2, Format: format, Legend: ChartLegend{Position: "top", ShowLegendKey: false}, Title: []RichTextRun{{Text: "3D Line Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, TickLabelSkip: 1, NumFmt: ChartNumFmt{CustomNumFmt: "General"}}, YAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, MajorUnit: 1, NumFmt: ChartNumFmt{CustomNumFmt: "General"}}}},
|
||||||
{sheetName: "Sheet2", cell: "X1", opts: &Chart{Type: Scatter, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Scatter Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
{sheetName: "Sheet2", cell: "X1", opts: &Chart{Type: Scatter, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Scatter Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
|
||||||
{sheetName: "Sheet2", cell: "P16", opts: &Chart{Type: Doughnut, Series: series3, Format: format, Legend: ChartLegend{Position: "right", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Doughnut Chart"}}, PlotArea: ChartPlotArea{ShowBubbleSize: false, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: false, ShowVal: false}, ShowBlanksAs: "zero", HoleSize: 30}},
|
{sheetName: "Sheet2", cell: "P16", opts: &Chart{Type: Doughnut, Series: series3, Format: format, Legend: ChartLegend{Position: "right", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Doughnut Chart"}}, PlotArea: ChartPlotArea{ShowBubbleSize: false, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: false, ShowVal: false}, ShowBlanksAs: "zero", HoleSize: 30}},
|
||||||
|
|
46
col.go
46
col.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mohae/deepcopy"
|
"github.com/tiendc/go-deepcopy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define the default cell size and EMU unit of measurement.
|
// Define the default cell size and EMU unit of measurement.
|
||||||
|
@ -450,6 +450,21 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
|
||||||
}
|
}
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
ws.mu.Lock()
|
ws.mu.Lock()
|
||||||
|
ws.setColStyle(minVal, maxVal, styleID)
|
||||||
|
ws.mu.Unlock()
|
||||||
|
if rows := len(ws.SheetData.Row); rows > 0 {
|
||||||
|
for col := minVal; col <= maxVal; col++ {
|
||||||
|
from, _ := CoordinatesToCellName(col, 1)
|
||||||
|
to, _ := CoordinatesToCellName(col, rows)
|
||||||
|
err = f.SetCellStyle(sheet, from, to, styleID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// setColStyle provides a function to set the style of a single column or
|
||||||
|
// multiple columns.
|
||||||
|
func (ws *xlsxWorksheet) setColStyle(minVal, maxVal, styleID int) {
|
||||||
if ws.Cols == nil {
|
if ws.Cols == nil {
|
||||||
ws.Cols = &xlsxCols{}
|
ws.Cols = &xlsxCols{}
|
||||||
}
|
}
|
||||||
|
@ -472,15 +487,6 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
|
||||||
fc.Width = c.Width
|
fc.Width = c.Width
|
||||||
return fc
|
return fc
|
||||||
})
|
})
|
||||||
ws.mu.Unlock()
|
|
||||||
if rows := len(ws.SheetData.Row); rows > 0 {
|
|
||||||
for col := minVal; col <= maxVal; col++ {
|
|
||||||
from, _ := CoordinatesToCellName(col, 1)
|
|
||||||
to, _ := CoordinatesToCellName(col, rows)
|
|
||||||
err = f.SetCellStyle(sheet, from, to, styleID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetColWidth provides a function to set the width of a single column or
|
// SetColWidth provides a function to set the width of a single column or
|
||||||
|
@ -504,6 +510,13 @@ func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error
|
||||||
f.mu.Unlock()
|
f.mu.Unlock()
|
||||||
ws.mu.Lock()
|
ws.mu.Lock()
|
||||||
defer ws.mu.Unlock()
|
defer ws.mu.Unlock()
|
||||||
|
ws.setColWidth(minVal, maxVal, width)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// setColWidth provides a function to set the width of a single column or
|
||||||
|
// multiple columns.
|
||||||
|
func (ws *xlsxWorksheet) setColWidth(minVal, maxVal int, width float64) {
|
||||||
col := xlsxCol{
|
col := xlsxCol{
|
||||||
Min: minVal,
|
Min: minVal,
|
||||||
Max: maxVal,
|
Max: maxVal,
|
||||||
|
@ -514,7 +527,7 @@ func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error
|
||||||
cols := xlsxCols{}
|
cols := xlsxCols{}
|
||||||
cols.Col = append(cols.Col, col)
|
cols.Col = append(cols.Col, col)
|
||||||
ws.Cols = &cols
|
ws.Cols = &cols
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
ws.Cols.Col = flatCols(col, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
ws.Cols.Col = flatCols(col, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||||
fc.BestFit = c.BestFit
|
fc.BestFit = c.BestFit
|
||||||
|
@ -525,7 +538,6 @@ func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error
|
||||||
fc.Style = c.Style
|
fc.Style = c.Style
|
||||||
return fc
|
return fc
|
||||||
})
|
})
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// flatCols provides a method for the column's operation functions to flatten
|
// flatCols provides a method for the column's operation functions to flatten
|
||||||
|
@ -533,7 +545,8 @@ func (f *File) SetColWidth(sheet, startCol, endCol string, width float64) error
|
||||||
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
|
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
|
||||||
var fc []xlsxCol
|
var fc []xlsxCol
|
||||||
for i := col.Min; i <= col.Max; i++ {
|
for i := col.Min; i <= col.Max; i++ {
|
||||||
c := deepcopy.Copy(col).(xlsxCol)
|
var c xlsxCol
|
||||||
|
deepcopy.Copy(&c, col)
|
||||||
c.Min, c.Max = i, i
|
c.Min, c.Max = i, i
|
||||||
fc = append(fc, c)
|
fc = append(fc, c)
|
||||||
}
|
}
|
||||||
|
@ -551,7 +564,8 @@ func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol)
|
||||||
fc[idx] = replacer(fc[idx], column)
|
fc[idx] = replacer(fc[idx], column)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c := deepcopy.Copy(column).(xlsxCol)
|
var c xlsxCol
|
||||||
|
deepcopy.Copy(&c, column)
|
||||||
c.Min, c.Max = i, i
|
c.Min, c.Max = i, i
|
||||||
fc = append(fc, c)
|
fc = append(fc, c)
|
||||||
}
|
}
|
||||||
|
|
4
crypt.go
4
crypt.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DataValidationType defined the type of data validation.
|
// DataValidationType defined the type of data validation.
|
||||||
type DataValidationType int
|
type DataValidationType byte
|
||||||
|
|
||||||
// Data validation types.
|
// Data validation types.
|
||||||
const (
|
const (
|
||||||
|
@ -36,7 +36,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DataValidationErrorStyle defined the style of data validation error alert.
|
// DataValidationErrorStyle defined the style of data validation error alert.
|
||||||
type DataValidationErrorStyle int
|
type DataValidationErrorStyle byte
|
||||||
|
|
||||||
// Data validation error styles.
|
// Data validation error styles.
|
||||||
const (
|
const (
|
||||||
|
@ -54,7 +54,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DataValidationOperator operator enum.
|
// DataValidationOperator operator enum.
|
||||||
type DataValidationOperator int
|
type DataValidationOperator byte
|
||||||
|
|
||||||
// Data validation operators.
|
// Data validation operators.
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
4
date.go
4
date.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
136
drawing.go
136
drawing.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -213,17 +213,15 @@ func (f *File) drawBaseChart(pa *cPlotArea, opts *Chart) *cPlotArea {
|
||||||
Ser: f.drawChartSeries(opts),
|
Ser: f.drawChartSeries(opts),
|
||||||
Shape: f.drawChartShape(opts),
|
Shape: f.drawChartShape(opts),
|
||||||
DLbls: f.drawChartDLbls(opts),
|
DLbls: f.drawChartDLbls(opts),
|
||||||
|
GapWidth: f.drawChartGapWidth(opts),
|
||||||
AxID: f.genAxID(opts),
|
AxID: f.genAxID(opts),
|
||||||
Overlap: &attrValInt{Val: intPtr(100)},
|
Overlap: f.drawChartOverlap(opts),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var ok bool
|
var ok bool
|
||||||
if *c[0].BarDir.Val, ok = plotAreaChartBarDir[opts.Type]; !ok {
|
if *c[0].BarDir.Val, ok = plotAreaChartBarDir[opts.Type]; !ok {
|
||||||
c[0].BarDir = nil
|
c[0].BarDir = nil
|
||||||
}
|
}
|
||||||
if *c[0].Overlap.Val, ok = plotAreaChartOverlap[opts.Type]; !ok {
|
|
||||||
c[0].Overlap = nil
|
|
||||||
}
|
|
||||||
catAx := f.drawPlotAreaCatAx(pa, opts)
|
catAx := f.drawPlotAreaCatAx(pa, opts)
|
||||||
valAx := f.drawPlotAreaValAx(pa, opts)
|
valAx := f.drawPlotAreaValAx(pa, opts)
|
||||||
charts := map[ChartType]*cPlotArea{
|
charts := map[ChartType]*cPlotArea{
|
||||||
|
@ -697,6 +695,35 @@ func (f *File) drawBubbleChart(pa *cPlotArea, opts *Chart) *cPlotArea {
|
||||||
return plotArea
|
return plotArea
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drawChartGapWidth provides a function to draw the c:gapWidth element by given
|
||||||
|
// format sets.
|
||||||
|
func (f *File) drawChartGapWidth(opts *Chart) *attrValInt {
|
||||||
|
for _, t := range barColChartTypes {
|
||||||
|
if t == opts.Type && opts.GapWidth != nil && *opts.GapWidth != 150 && *opts.GapWidth <= 500 {
|
||||||
|
return &attrValInt{intPtr(int(*opts.GapWidth))}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// drawChartOverlap provides a function to draw the c:overlap element by given
|
||||||
|
// format sets.
|
||||||
|
func (f *File) drawChartOverlap(opts *Chart) *attrValInt {
|
||||||
|
var val *attrValInt
|
||||||
|
if _, ok := plotAreaChartOverlap[opts.Type]; ok {
|
||||||
|
val = &attrValInt{intPtr(100)}
|
||||||
|
}
|
||||||
|
if opts.Overlap != nil && -100 <= *opts.Overlap && *opts.Overlap <= 100 {
|
||||||
|
val = &attrValInt{intPtr(*opts.Overlap)}
|
||||||
|
}
|
||||||
|
for _, t := range barColChartTypes {
|
||||||
|
if t == opts.Type {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// drawChartShape provides a function to draw the c:shape element by given
|
// drawChartShape provides a function to draw the c:shape element by given
|
||||||
// format sets.
|
// format sets.
|
||||||
func (f *File) drawChartShape(opts *Chart) *attrValString {
|
func (f *File) drawChartShape(opts *Chart) *attrValString {
|
||||||
|
@ -1001,6 +1028,10 @@ func (f *File) drawChartSeriesDLbls(i int, opts *Chart) *cDLbls {
|
||||||
dLbls.DLblPos = &attrValString{Val: stringPtr(chartDataLabelsPositionTypes[opts.Series[i].DataLabelPosition])}
|
dLbls.DLblPos = &attrValString{Val: stringPtr(chartDataLabelsPositionTypes[opts.Series[i].DataLabelPosition])}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dLbl := opts.Series[i].DataLabel
|
||||||
|
dLbls.SpPr = f.drawShapeFill(dLbl.Fill, dLbls.SpPr)
|
||||||
|
dLbls.TxPr = &cTxPr{BodyPr: aBodyPr{}, P: aP{PPr: &aPPr{DefRPr: aRPr{}}}}
|
||||||
|
drawChartFont(&dLbl.Font, &dLbls.TxPr.P.PPr.DefRPr)
|
||||||
return dLbls
|
return dLbls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,6 +1287,12 @@ func (f *File) drawPlotAreaTxPr(opts *ChartAxis) *cTxPr {
|
||||||
}
|
}
|
||||||
if opts != nil {
|
if opts != nil {
|
||||||
drawChartFont(&opts.Font, &cTxPr.P.PPr.DefRPr)
|
drawChartFont(&opts.Font, &cTxPr.P.PPr.DefRPr)
|
||||||
|
if -90 <= opts.Alignment.TextRotation && opts.Alignment.TextRotation <= 90 {
|
||||||
|
cTxPr.BodyPr.Rot = opts.Alignment.TextRotation * 60000
|
||||||
|
}
|
||||||
|
if idx := inStrSlice(supportedDrawingTextVerticalType, opts.Alignment.Vertical, true); idx != -1 {
|
||||||
|
cTxPr.BodyPr.Vert = supportedDrawingTextVerticalType[idx]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cTxPr
|
return cTxPr
|
||||||
}
|
}
|
||||||
|
@ -1447,13 +1484,14 @@ func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *GraphicOpt
|
||||||
// deleteDrawing provides a function to delete the chart graphic frame and
|
// deleteDrawing provides a function to delete the chart graphic frame and
|
||||||
// returns deleted embed relationships ID (for unique picture cell anchor) by
|
// returns deleted embed relationships ID (for unique picture cell anchor) by
|
||||||
// given coordinates and graphic type.
|
// given coordinates and graphic type.
|
||||||
func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (string, error) {
|
func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) ([]string, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
rID string
|
rID string
|
||||||
rIDs []string
|
delRID, refRID []string
|
||||||
|
rIDMaps = map[string]int{}
|
||||||
wsDr *xlsxWsDr
|
wsDr *xlsxWsDr
|
||||||
deTwoCellAnchor *decodeCellAnchor
|
deCellAnchor *decodeCellAnchor
|
||||||
)
|
)
|
||||||
xdrCellAnchorFuncs := map[string]func(anchor *xdrCellAnchor) bool{
|
xdrCellAnchorFuncs := map[string]func(anchor *xdrCellAnchor) bool{
|
||||||
"Chart": func(anchor *xdrCellAnchor) bool { return anchor.Pic == nil },
|
"Chart": func(anchor *xdrCellAnchor) bool { return anchor.Pic == nil },
|
||||||
|
@ -1465,54 +1503,70 @@ func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) (stri
|
||||||
}
|
}
|
||||||
onAnchorCell := func(c, r int) bool { return c == col && r == row }
|
onAnchorCell := func(c, r int) bool { return c == col && r == row }
|
||||||
if wsDr, _, err = f.drawingParser(drawingXML); err != nil {
|
if wsDr, _, err = f.drawingParser(drawingXML); err != nil {
|
||||||
return rID, err
|
return delRID, err
|
||||||
}
|
}
|
||||||
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
|
deleteCellAnchor := func(ca []*xdrCellAnchor) ([]*xdrCellAnchor, error) {
|
||||||
if err = nil; wsDr.TwoCellAnchor[idx].From != nil && xdrCellAnchorFuncs[drawingType](wsDr.TwoCellAnchor[idx]) {
|
for idx := 0; idx < len(ca); idx++ {
|
||||||
if onAnchorCell(wsDr.TwoCellAnchor[idx].From.Col, wsDr.TwoCellAnchor[idx].From.Row) {
|
if err = nil; ca[idx].From != nil && xdrCellAnchorFuncs[drawingType](ca[idx]) {
|
||||||
rID, _ = extractEmbedRID(wsDr.TwoCellAnchor[idx].Pic, nil, rIDs)
|
rID = extractEmbedRID(ca[idx].Pic, nil)
|
||||||
wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...)
|
rIDMaps[rID]++
|
||||||
|
if onAnchorCell(ca[idx].From.Col, ca[idx].From.Row) {
|
||||||
|
refRID = append(refRID, rID)
|
||||||
|
ca = append(ca[:idx], ca[idx+1:]...)
|
||||||
idx--
|
idx--
|
||||||
|
rIDMaps[rID]--
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, rIDs = extractEmbedRID(wsDr.TwoCellAnchor[idx].Pic, nil, rIDs)
|
deCellAnchor = new(decodeCellAnchor)
|
||||||
|
if err = f.xmlNewDecoder(strings.NewReader("<decodeCellAnchor>" + ca[idx].GraphicFrame + "</decodeCellAnchor>")).
|
||||||
|
Decode(deCellAnchor); err != nil && err != io.EOF {
|
||||||
|
return ca, err
|
||||||
}
|
}
|
||||||
}
|
if err = nil; deCellAnchor.From != nil && decodeCellAnchorFuncs[drawingType](deCellAnchor) {
|
||||||
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
|
rID = extractEmbedRID(nil, deCellAnchor.Pic)
|
||||||
deTwoCellAnchor = new(decodeCellAnchor)
|
rIDMaps[rID]++
|
||||||
if err = f.xmlNewDecoder(strings.NewReader("<decodeCellAnchor>" + wsDr.TwoCellAnchor[idx].GraphicFrame + "</decodeCellAnchor>")).
|
if onAnchorCell(deCellAnchor.From.Col, deCellAnchor.From.Row) {
|
||||||
Decode(deTwoCellAnchor); err != nil && err != io.EOF {
|
refRID = append(refRID, rID)
|
||||||
return rID, err
|
ca = append(ca[:idx], ca[idx+1:]...)
|
||||||
}
|
|
||||||
if err = nil; deTwoCellAnchor.From != nil && decodeCellAnchorFuncs[drawingType](deTwoCellAnchor) {
|
|
||||||
if onAnchorCell(deTwoCellAnchor.From.Col, deTwoCellAnchor.From.Row) {
|
|
||||||
rID, _ = extractEmbedRID(nil, deTwoCellAnchor.Pic, rIDs)
|
|
||||||
wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...)
|
|
||||||
idx--
|
idx--
|
||||||
continue
|
rIDMaps[rID]--
|
||||||
}
|
|
||||||
_, rIDs = extractEmbedRID(nil, deTwoCellAnchor.Pic, rIDs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if inStrSlice(rIDs, rID, true) != -1 {
|
}
|
||||||
rID = ""
|
return ca, err
|
||||||
|
}
|
||||||
|
if wsDr.OneCellAnchor, err = deleteCellAnchor(wsDr.OneCellAnchor); err != nil {
|
||||||
|
return delRID, err
|
||||||
|
}
|
||||||
|
if wsDr.TwoCellAnchor, err = deleteCellAnchor(wsDr.TwoCellAnchor); err != nil {
|
||||||
|
return delRID, err
|
||||||
}
|
}
|
||||||
f.Drawings.Store(drawingXML, wsDr)
|
f.Drawings.Store(drawingXML, wsDr)
|
||||||
return rID, err
|
return getUnusedCellAnchorRID(delRID, refRID, rIDMaps), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractEmbedRID returns embed relationship ID and all relationship ID lists
|
// extractEmbedRID returns embed relationship ID by giving cell anchor.
|
||||||
// for giving cell anchor.
|
func extractEmbedRID(pic *xlsxPic, decodePic *decodePic) string {
|
||||||
func extractEmbedRID(pic *xlsxPic, decodePic *decodePic, rIDs []string) (string, []string) {
|
var rID string
|
||||||
if pic != nil {
|
if pic != nil {
|
||||||
rIDs = append(rIDs, pic.BlipFill.Blip.Embed)
|
rID = pic.BlipFill.Blip.Embed
|
||||||
return pic.BlipFill.Blip.Embed, rIDs
|
|
||||||
}
|
}
|
||||||
if decodePic != nil {
|
if decodePic != nil {
|
||||||
rIDs = append(rIDs, decodePic.BlipFill.Blip.Embed)
|
rID = decodePic.BlipFill.Blip.Embed
|
||||||
return decodePic.BlipFill.Blip.Embed, rIDs
|
|
||||||
}
|
}
|
||||||
return "", rIDs
|
return rID
|
||||||
|
}
|
||||||
|
|
||||||
|
// getUnusedCellAnchorRID returns relationship ID lists in the cell anchor which
|
||||||
|
// for remove.
|
||||||
|
func getUnusedCellAnchorRID(delRID, refRID []string, rIDMaps map[string]int) []string {
|
||||||
|
for _, rID := range refRID {
|
||||||
|
if rIDMaps[rID] == 0 && inStrSlice(delRID, rID, false) == -1 {
|
||||||
|
delRID = append(delRID, rID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return delRID
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteDrawingRels provides a function to delete relationships in
|
// deleteDrawingRels provides a function to delete relationships in
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
16
errors.go
16
errors.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -88,6 +88,9 @@ var (
|
||||||
// ErrOutlineLevel defined the error message on receive an invalid outline
|
// ErrOutlineLevel defined the error message on receive an invalid outline
|
||||||
// level number.
|
// level number.
|
||||||
ErrOutlineLevel = errors.New("invalid outline level")
|
ErrOutlineLevel = errors.New("invalid outline level")
|
||||||
|
// ErrPageSetupAdjustTo defined the error message for receiving a page setup
|
||||||
|
// adjust to value exceeds limit.
|
||||||
|
ErrPageSetupAdjustTo = errors.New("adjust to value must be between 10 and 400")
|
||||||
// ErrParameterInvalid defined the error message on receive the invalid
|
// ErrParameterInvalid defined the error message on receive the invalid
|
||||||
// parameter.
|
// parameter.
|
||||||
ErrParameterInvalid = errors.New("parameter is invalid")
|
ErrParameterInvalid = errors.New("parameter is invalid")
|
||||||
|
@ -132,6 +135,9 @@ var (
|
||||||
// ErrSparklineType defined the error message on receive the invalid
|
// ErrSparklineType defined the error message on receive the invalid
|
||||||
// sparkline Type parameters.
|
// sparkline Type parameters.
|
||||||
ErrSparklineType = errors.New("parameter 'Type' must be 'line', 'column' or 'win_loss'")
|
ErrSparklineType = errors.New("parameter 'Type' must be 'line', 'column' or 'win_loss'")
|
||||||
|
// ErrStreamSetColStyle defined the error message on set column style in
|
||||||
|
// stream writing mode.
|
||||||
|
ErrStreamSetColStyle = errors.New("must call the SetColStyle function before the SetRow function")
|
||||||
// ErrStreamSetColWidth defined the error message on set column width in
|
// ErrStreamSetColWidth defined the error message on set column width in
|
||||||
// stream writing mode.
|
// stream writing mode.
|
||||||
ErrStreamSetColWidth = errors.New("must call the SetColWidth function before the SetRow function")
|
ErrStreamSetColWidth = errors.New("must call the SetColWidth function before the SetRow function")
|
||||||
|
@ -249,6 +255,12 @@ func newInvalidNameError(name string) error {
|
||||||
return fmt.Errorf("invalid name %q, the name should be starts with a letter or underscore, can not include a space or character, and can not conflict with an existing name in the workbook", name)
|
return fmt.Errorf("invalid name %q, the name should be starts with a letter or underscore, can not include a space or character, and can not conflict with an existing name in the workbook", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newInvalidPageLayoutValueError defined the error message on receiving the invalid
|
||||||
|
// page layout options value.
|
||||||
|
func newInvalidPageLayoutValueError(name, value, msg string) error {
|
||||||
|
return fmt.Errorf("invalid %s value %q, acceptable value should be one of %s", name, value, msg)
|
||||||
|
}
|
||||||
|
|
||||||
// newInvalidRowNumberError defined the error message on receiving the invalid
|
// newInvalidRowNumberError defined the error message on receiving the invalid
|
||||||
// row number.
|
// row number.
|
||||||
func newInvalidRowNumberError(row int) error {
|
func newInvalidRowNumberError(row int) error {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
//
|
//
|
||||||
// See https://xuri.me/excelize for more information about this package.
|
// See https://xuri.me/excelize for more information about this package.
|
||||||
package excelize
|
package excelize
|
||||||
|
|
|
@ -628,7 +628,7 @@ func TestWriteArrayFormula(t *testing.T) {
|
||||||
valCell := cell(1, i+firstResLine)
|
valCell := cell(1, i+firstResLine)
|
||||||
assocCell := cell(2, i+firstResLine)
|
assocCell := cell(2, i+firstResLine)
|
||||||
|
|
||||||
assert.NoError(t, f.SetCellInt("Sheet1", valCell, values[i]))
|
assert.NoError(t, f.SetCellInt("Sheet1", valCell, int64(values[i])))
|
||||||
assert.NoError(t, f.SetCellStr("Sheet1", assocCell, sample[assoc[i]]))
|
assert.NoError(t, f.SetCellStr("Sheet1", assocCell, sample[assoc[i]]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,8 +642,8 @@ func TestWriteArrayFormula(t *testing.T) {
|
||||||
stdevCell := cell(i+2, 4)
|
stdevCell := cell(i+2, 4)
|
||||||
calcStdevCell := cell(i+2, 5)
|
calcStdevCell := cell(i+2, 5)
|
||||||
|
|
||||||
assert.NoError(t, f.SetCellInt("Sheet1", calcAvgCell, average(i)))
|
assert.NoError(t, f.SetCellInt("Sheet1", calcAvgCell, int64(average(i))))
|
||||||
assert.NoError(t, f.SetCellInt("Sheet1", calcStdevCell, stdev(i)))
|
assert.NoError(t, f.SetCellInt("Sheet1", calcStdevCell, int64(stdev(i))))
|
||||||
|
|
||||||
// Average can be done with AVERAGEIF
|
// Average can be done with AVERAGEIF
|
||||||
assert.NoError(t, f.SetCellFormula("Sheet1", avgCell, fmt.Sprintf("ROUND(AVERAGEIF(%s,%s,%s),0)", assocRange, nameCell, valRange)))
|
assert.NoError(t, f.SetCellFormula("Sheet1", avgCell, fmt.Sprintf("ROUND(AVERAGEIF(%s,%s,%s),0)", assocRange, nameCell, valRange)))
|
||||||
|
@ -870,11 +870,17 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetCellStyleLangNumberFormat(t *testing.T) {
|
func TestSetCellStyleLangNumberFormat(t *testing.T) {
|
||||||
rawCellValues := [][]string{{"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}
|
rawCellValues := make([][]string, 42)
|
||||||
|
for i := 0; i < 42; i++ {
|
||||||
|
rawCellValues[i] = []string{"45162"}
|
||||||
|
}
|
||||||
for lang, expected := range map[CultureName][][]string{
|
for lang, expected := range map[CultureName][][]string{
|
||||||
CultureNameUnknown: rawCellValues,
|
CultureNameUnknown: rawCellValues,
|
||||||
CultureNameEnUS: {{"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"0:00:00"}, {"0:00:00"}, {"0:00:00"}, {"0:00:00"}, {"45162"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
CultureNameEnUS: {{"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"0:00:00"}, {"0:00:00"}, {"0:00:00"}, {"0:00:00"}, {"45162"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
|
CultureNameJaJP: {{"R5.8.24"}, {"令和5年8月24日"}, {"令和5年8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"0時00分"}, {"0時00分00秒"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"R5.8.24"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"令和5年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
|
CultureNameKoKR: {{"4356年 08月 24日"}, {"08-24"}, {"08-24"}, {"08-24-56"}, {"4356년 08월 24일"}, {"0시 00분"}, {"0시 00분 00초"}, {"4356-08-24"}, {"4356-08-24"}, {"4356年 08月 24日"}, {"4356年 08月 24日"}, {"08-24"}, {"4356-08-24"}, {"4356-08-24"}, {"08-24"}, {"4356-08-24"}, {"4356-08-24"}, {"4356年 08月 24日"}, {"08-24"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
CultureNameZhCN: {{"2023年8月"}, {"8月24日"}, {"8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"0时00分"}, {"0时00分00秒"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"2023年8月"}, {"8月24日"}, {"2023年8月"}, {"8月24日"}, {"8月24日"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
CultureNameZhCN: {{"2023年8月"}, {"8月24日"}, {"8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"0时00分"}, {"0时00分00秒"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"2023年8月"}, {"8月24日"}, {"2023年8月"}, {"8月24日"}, {"8月24日"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
|
CultureNameZhTW: {{"112/8/24"}, {"112年8月24日"}, {"112年8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"00時00分"}, {"00時00分00秒"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112/8/24"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
} {
|
} {
|
||||||
f, err := prepareTestBook5(Options{CultureInfo: lang})
|
f, err := prepareTestBook5(Options{CultureInfo: lang})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -886,7 +892,10 @@ func TestSetCellStyleLangNumberFormat(t *testing.T) {
|
||||||
// Test apply language number format code with date and time pattern
|
// Test apply language number format code with date and time pattern
|
||||||
for lang, expected := range map[CultureName][][]string{
|
for lang, expected := range map[CultureName][][]string{
|
||||||
CultureNameEnUS: {{"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"00:00:00"}, {"00:00:00"}, {"00:00:00"}, {"00:00:00"}, {"45162"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
CultureNameEnUS: {{"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"00:00:00"}, {"00:00:00"}, {"00:00:00"}, {"00:00:00"}, {"45162"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
|
CultureNameJaJP: {{"R5.8.24"}, {"令和5年8月24日"}, {"令和5年8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"R5.8.24"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"令和5年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
|
CultureNameKoKR: {{"4356年 08月 24日"}, {"08-24"}, {"08-24"}, {"4356-8-24"}, {"4356년 08월 24일"}, {"00:00:00"}, {"00:00:00"}, {"4356-08-24"}, {"4356-08-24"}, {"4356年 08月 24日"}, {"4356年 08月 24日"}, {"08-24"}, {"4356-08-24"}, {"4356-08-24"}, {"08-24"}, {"4356-08-24"}, {"4356-08-24"}, {"4356年 08月 24日"}, {"08-24"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
CultureNameZhCN: {{"2023年8月"}, {"8月24日"}, {"8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"2023年8月"}, {"8月24日"}, {"2023年8月"}, {"8月24日"}, {"8月24日"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
CultureNameZhCN: {{"2023年8月"}, {"8月24日"}, {"8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"2023年8月"}, {"8月24日"}, {"2023年8月"}, {"8月24日"}, {"8月24日"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
|
CultureNameZhTW: {{"112/8/24"}, {"112年8月24日"}, {"112年8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112/8/24"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}},
|
||||||
} {
|
} {
|
||||||
f, err := prepareTestBook5(Options{CultureInfo: lang, ShortDatePattern: "yyyy-M-d", LongTimePattern: "hh:mm:ss"})
|
f, err := prepareTestBook5(Options{CultureInfo: lang, ShortDatePattern: "yyyy-M-d", LongTimePattern: "hh:mm:ss"})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
4
file.go
4
file.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
16
go.mod
16
go.mod
|
@ -1,17 +1,17 @@
|
||||||
module github.com/xuri/excelize/v2
|
module github.com/xuri/excelize/v2
|
||||||
|
|
||||||
go 1.18
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
|
||||||
github.com/richardlehane/mscfb v1.0.4
|
github.com/richardlehane/mscfb v1.0.4
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d
|
github.com/tiendc/go-deepcopy v1.2.0
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7
|
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6
|
||||||
golang.org/x/crypto v0.28.0
|
github.com/xuri/nfp v0.0.0-20250111060730-82a408b9aa71
|
||||||
|
golang.org/x/crypto v0.32.0
|
||||||
golang.org/x/image v0.18.0
|
golang.org/x/image v0.18.0
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.34.0
|
||||||
golang.org/x/text v0.19.0
|
golang.org/x/text v0.21.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
28
go.sum
28
go.sum
|
@ -1,7 +1,5 @@
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||||
|
@ -9,20 +7,22 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7
|
||||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||||
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
|
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
|
||||||
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
|
github.com/tiendc/go-deepcopy v1.2.0 h1:6vCCs+qdLQHzFqY1fcPirsAWOmrLbuccilfp8UzD1Qo=
|
||||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
github.com/tiendc/go-deepcopy v1.2.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
|
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6 h1:8m6DWBG+dlFNbx5ynvrE7NgI+Y7OlZVMVTpayoW+rCc=
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
github.com/xuri/nfp v0.0.0-20250111060730-82a408b9aa71 h1:hOh7aVDrvGJRxzXrQbDY8E+02oaI//5cHL+97oYpEPw=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
github.com/xuri/nfp v0.0.0-20250111060730-82a408b9aa71/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||||
|
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||||
|
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
13
lib.go
13
lib.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -652,11 +652,16 @@ func getRootElement(d *xml.Decoder) []xml.Attr {
|
||||||
case xml.StartElement:
|
case xml.StartElement:
|
||||||
tokenIdx++
|
tokenIdx++
|
||||||
if tokenIdx == 1 {
|
if tokenIdx == 1 {
|
||||||
|
var ns bool
|
||||||
for i := 0; i < len(startElement.Attr); i++ {
|
for i := 0; i < len(startElement.Attr); i++ {
|
||||||
if startElement.Attr[i].Value == NameSpaceSpreadSheet.Value {
|
if startElement.Attr[i].Value == NameSpaceSpreadSheet.Value &&
|
||||||
startElement.Attr[i] = NameSpaceSpreadSheet
|
startElement.Attr[i].Name == NameSpaceSpreadSheet.Name {
|
||||||
|
ns = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !ns {
|
||||||
|
startElement.Attr = append(startElement.Attr, NameSpaceSpreadSheet)
|
||||||
|
}
|
||||||
return startElement.Attr
|
return startElement.Attr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
lib_test.go
10
lib_test.go
|
@ -7,7 +7,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -289,6 +288,10 @@ func TestBytesReplace(t *testing.T) {
|
||||||
|
|
||||||
func TestGetRootElement(t *testing.T) {
|
func TestGetRootElement(t *testing.T) {
|
||||||
assert.Len(t, getRootElement(xml.NewDecoder(strings.NewReader(""))), 0)
|
assert.Len(t, getRootElement(xml.NewDecoder(strings.NewReader(""))), 0)
|
||||||
|
// Test get workbook root element which all workbook XML namespace has prefix
|
||||||
|
f := NewFile()
|
||||||
|
d := f.xmlNewDecoder(bytes.NewReader([]byte(`<x:workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"></x:workbook>`)))
|
||||||
|
assert.Len(t, getRootElement(d), 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetIgnorableNameSpace(t *testing.T) {
|
func TestSetIgnorableNameSpace(t *testing.T) {
|
||||||
|
@ -358,9 +361,6 @@ func TestReadBytes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnzipToTemp(t *testing.T) {
|
func TestUnzipToTemp(t *testing.T) {
|
||||||
if ver := runtime.Version(); strings.HasPrefix(ver, "go1.19") || strings.HasPrefix(ver, "go1.2") {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
os.Setenv("TMPDIR", "test")
|
os.Setenv("TMPDIR", "test")
|
||||||
defer os.Unsetenv("TMPDIR")
|
defer os.Unsetenv("TMPDIR")
|
||||||
assert.NoError(t, os.Chmod(os.TempDir(), 0o444))
|
assert.NoError(t, os.Chmod(os.TempDir(), 0o444))
|
||||||
|
@ -378,7 +378,7 @@ func TestUnzipToTemp(t *testing.T) {
|
||||||
"\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
|
"\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
|
||||||
"00000000PK\x01\x0200000000" +
|
"00000000PK\x01\x0200000000" +
|
||||||
"0000000000000000\v\x00\x00\x00" +
|
"0000000000000000\v\x00\x00\x00" +
|
||||||
"\x00\x0000PK\x05\x06000000\x05\x000000" +
|
"\x00\x0000PK\x05\x06000000\x05\x00\xfd\x00\x00\x00" +
|
||||||
"\v\x00\x00\x00\x00\x00")
|
"\v\x00\x00\x00\x00\x00")
|
||||||
z, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
|
z, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
4
merge.go
4
merge.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
178
numfmt.go
178
numfmt.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -57,7 +57,10 @@ type CultureName byte
|
||||||
const (
|
const (
|
||||||
CultureNameUnknown CultureName = iota
|
CultureNameUnknown CultureName = iota
|
||||||
CultureNameEnUS
|
CultureNameEnUS
|
||||||
|
CultureNameJaJP
|
||||||
|
CultureNameKoKR
|
||||||
CultureNameZhCN
|
CultureNameZhCN
|
||||||
|
CultureNameZhTW
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -791,7 +794,7 @@ var (
|
||||||
31748: {tags: []string{"zh-Hant"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
31748: {tags: []string{"zh-Hant"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
||||||
3076: {tags: []string{"zh-HK"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
3076: {tags: []string{"zh-HK"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
||||||
5124: {tags: []string{"zh-MO"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
5124: {tags: []string{"zh-MO"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
||||||
1028: {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
|
1028: {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2, useGannen: true},
|
||||||
9: {tags: []string{"en"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0], weekdayNames: weekdayNamesEnglish, weekdayNamesAbbr: weekdayNamesEnglishAbbr},
|
9: {tags: []string{"en"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0], weekdayNames: weekdayNamesEnglish, weekdayNamesAbbr: weekdayNamesEnglishAbbr},
|
||||||
4096: {tags: []string{
|
4096: {tags: []string{
|
||||||
"aa", "aa-DJ", "aa-ER", "aa-ER", "aa-NA", "agq", "agq-CM", "ak", "ak-GH", "sq-ML",
|
"aa", "aa-DJ", "aa-ER", "aa-ER", "aa-NA", "agq", "agq-CM", "ak", "ak-GH", "sq-ML",
|
||||||
|
@ -1168,6 +1171,10 @@ var (
|
||||||
"JA-JP-X-GANNEN": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr},
|
"JA-JP-X-GANNEN": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr},
|
||||||
"JA-JP-X-GANNEN,80": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr, useGannen: true},
|
"JA-JP-X-GANNEN,80": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr, useGannen: true},
|
||||||
}
|
}
|
||||||
|
// republicOfChinaYear defined start time of the Republic of China
|
||||||
|
republicOfChinaYear = time.Date(1912, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
// republicOfChinaEraName defined the Republic of China era name for the Republic of China calendar.
|
||||||
|
republicOfChinaEraName = []string{"\u4e2d\u83ef\u6c11\u570b", "\u6c11\u570b", "\u524d"}
|
||||||
// japaneseEraYears list the Japanese era name periods.
|
// japaneseEraYears list the Japanese era name periods.
|
||||||
japaneseEraYears = []time.Time{
|
japaneseEraYears = []time.Time{
|
||||||
time.Date(1868, time.August, 8, 0, 0, 0, 0, time.UTC),
|
time.Date(1868, time.August, 8, 0, 0, 0, 0, time.UTC),
|
||||||
|
@ -4634,9 +4641,27 @@ var (
|
||||||
return r.Replace(s)
|
return r.Replace(s)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
// langNumFmtFunc defines functions to apply language number format code.
|
||||||
|
langNumFmtFunc = map[CultureName]func(f *File, numFmtID int) string{
|
||||||
|
CultureNameEnUS: func(f *File, numFmtID int) string {
|
||||||
|
return f.langNumFmtFuncEnUS(numFmtID)
|
||||||
|
},
|
||||||
|
CultureNameJaJP: func(f *File, numFmtID int) string {
|
||||||
|
return f.langNumFmtFuncJaJP(numFmtID)
|
||||||
|
},
|
||||||
|
CultureNameKoKR: func(f *File, numFmtID int) string {
|
||||||
|
return f.langNumFmtFuncKoKR(numFmtID)
|
||||||
|
},
|
||||||
|
CultureNameZhCN: func(f *File, numFmtID int) string {
|
||||||
|
return f.langNumFmtFuncZhCN(numFmtID)
|
||||||
|
},
|
||||||
|
CultureNameZhTW: func(f *File, numFmtID int) string {
|
||||||
|
return f.langNumFmtFuncZhTW(numFmtID)
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// getSupportedLanguageInfo returns language infomation by giving language code.
|
// getSupportedLanguageInfo returns language information by giving language code.
|
||||||
// This function does not support different calendar type of the language
|
// This function does not support different calendar type of the language
|
||||||
// currently. For example: the hexadecimal language code 3010429 (fa-IR,301)
|
// currently. For example: the hexadecimal language code 3010429 (fa-IR,301)
|
||||||
// will be convert to 0429 (fa-IR).
|
// will be convert to 0429 (fa-IR).
|
||||||
|
@ -4694,6 +4719,54 @@ func (f *File) langNumFmtFuncEnUS(numFmtID int) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// langNumFmtFuncJaJP returns number format code by given date and time pattern
|
||||||
|
// for country code ja-jp.
|
||||||
|
func (f *File) langNumFmtFuncJaJP(numFmtID int) string {
|
||||||
|
if numFmtID == 30 && f.options.ShortDatePattern != "" {
|
||||||
|
return f.options.ShortDatePattern
|
||||||
|
}
|
||||||
|
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
|
||||||
|
return f.options.LongTimePattern
|
||||||
|
}
|
||||||
|
return langNumFmt["ja-jp"][numFmtID]
|
||||||
|
}
|
||||||
|
|
||||||
|
// langNumFmtFuncKoKR returns number format code by given date and time pattern
|
||||||
|
// for country code ko-kr.
|
||||||
|
func (f *File) langNumFmtFuncKoKR(numFmtID int) string {
|
||||||
|
if numFmtID == 30 && f.options.ShortDatePattern != "" {
|
||||||
|
return f.options.ShortDatePattern
|
||||||
|
}
|
||||||
|
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
|
||||||
|
return f.options.LongTimePattern
|
||||||
|
}
|
||||||
|
return langNumFmt["ko-kr"][numFmtID]
|
||||||
|
}
|
||||||
|
|
||||||
|
// langNumFmtFuncZhCN returns number format code by given date and time pattern
|
||||||
|
// for country code zh-cn.
|
||||||
|
func (f *File) langNumFmtFuncZhCN(numFmtID int) string {
|
||||||
|
if numFmtID == 30 && f.options.ShortDatePattern != "" {
|
||||||
|
return f.options.ShortDatePattern
|
||||||
|
}
|
||||||
|
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
|
||||||
|
return f.options.LongTimePattern
|
||||||
|
}
|
||||||
|
return langNumFmt["zh-cn"][numFmtID]
|
||||||
|
}
|
||||||
|
|
||||||
|
// langNumFmtFuncZhTW returns number format code by given date and time pattern
|
||||||
|
// for country code zh-tw.
|
||||||
|
func (f *File) langNumFmtFuncZhTW(numFmtID int) string {
|
||||||
|
if numFmtID == 30 && f.options.ShortDatePattern != "" {
|
||||||
|
return f.options.ShortDatePattern
|
||||||
|
}
|
||||||
|
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
|
||||||
|
return f.options.LongTimePattern
|
||||||
|
}
|
||||||
|
return langNumFmt["zh-tw"][numFmtID]
|
||||||
|
}
|
||||||
|
|
||||||
// checkDateTimePattern check and validate date and time options field value.
|
// checkDateTimePattern check and validate date and time options field value.
|
||||||
func (f *File) checkDateTimePattern() error {
|
func (f *File) checkDateTimePattern() error {
|
||||||
for _, pattern := range []string{f.options.LongDatePattern, f.options.LongTimePattern, f.options.ShortDatePattern} {
|
for _, pattern := range []string{f.options.LongDatePattern, f.options.LongTimePattern, f.options.ShortDatePattern} {
|
||||||
|
@ -4770,18 +4843,6 @@ func (f *File) extractNumFmtDecimal(fmtCode string) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// langNumFmtFuncZhCN returns number format code by given date and time pattern
|
|
||||||
// for country code zh-cn.
|
|
||||||
func (f *File) langNumFmtFuncZhCN(numFmtID int) string {
|
|
||||||
if numFmtID == 30 && f.options.ShortDatePattern != "" {
|
|
||||||
return f.options.ShortDatePattern
|
|
||||||
}
|
|
||||||
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
|
|
||||||
return f.options.LongTimePattern
|
|
||||||
}
|
|
||||||
return langNumFmt["zh-cn"][numFmtID]
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBuiltInNumFmtCode convert number format index to number format code with
|
// getBuiltInNumFmtCode convert number format index to number format code with
|
||||||
// specified locale and language.
|
// specified locale and language.
|
||||||
func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) {
|
func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) {
|
||||||
|
@ -4789,11 +4850,8 @@ func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) {
|
||||||
return fmtCode, true
|
return fmtCode, true
|
||||||
}
|
}
|
||||||
if isLangNumFmt(numFmtID) {
|
if isLangNumFmt(numFmtID) {
|
||||||
if f.options.CultureInfo == CultureNameEnUS {
|
if fn, ok := langNumFmtFunc[f.options.CultureInfo]; ok {
|
||||||
return f.langNumFmtFuncEnUS(numFmtID), true
|
return fn(f, numFmtID), true
|
||||||
}
|
|
||||||
if f.options.CultureInfo == CultureNameZhCN {
|
|
||||||
return f.langNumFmtFuncZhCN(numFmtID), true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false
|
return "", false
|
||||||
|
@ -6912,23 +6970,13 @@ func eraYear(t time.Time) (int, int) {
|
||||||
return i, year
|
return i, year
|
||||||
}
|
}
|
||||||
|
|
||||||
// yearsHandler will be handling years in the date and times types tokens for a
|
// japaneseYearHandler handling the Japanease calendar years.
|
||||||
// number format expression.
|
func (nf *numberFormat) japaneseYearHandler(token nfp.Token, langInfo languageInfo) {
|
||||||
func (nf *numberFormat) yearsHandler(token nfp.Token) {
|
|
||||||
if strings.Contains(strings.ToUpper(token.TValue), "Y") {
|
|
||||||
if len(token.TValue) <= 2 {
|
|
||||||
nf.result += strconv.Itoa(nf.t.Year())[2:]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
nf.result += strconv.Itoa(nf.t.Year())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.Contains(strings.ToUpper(token.TValue), "G") {
|
if strings.Contains(strings.ToUpper(token.TValue), "G") {
|
||||||
i, year := eraYear(nf.t)
|
i, year := eraYear(nf.t)
|
||||||
if year == -1 {
|
if year == -1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
langInfo, _ := getSupportedLanguageInfo(nf.localCode)
|
|
||||||
nf.useGannen = langInfo.useGannen
|
nf.useGannen = langInfo.useGannen
|
||||||
switch len(token.TValue) {
|
switch len(token.TValue) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -6939,7 +6987,6 @@ func (nf *numberFormat) yearsHandler(token nfp.Token) {
|
||||||
default:
|
default:
|
||||||
nf.result += japaneseEraNames[i]
|
nf.result += japaneseEraNames[i]
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if strings.Contains(strings.ToUpper(token.TValue), "E") {
|
if strings.Contains(strings.ToUpper(token.TValue), "E") {
|
||||||
_, year := eraYear(nf.t)
|
_, year := eraYear(nf.t)
|
||||||
|
@ -6961,6 +7008,69 @@ func (nf *numberFormat) yearsHandler(token nfp.Token) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// republicOfChinaYearHandler handling the Republic of China calendar years.
|
||||||
|
func (nf *numberFormat) republicOfChinaYearHandler(token nfp.Token, langInfo languageInfo) {
|
||||||
|
if strings.Contains(strings.ToUpper(token.TValue), "G") {
|
||||||
|
year := nf.t.Year() - republicOfChinaYear.Year() + 1
|
||||||
|
if year == 1 {
|
||||||
|
nf.useGannen = langInfo.useGannen
|
||||||
|
}
|
||||||
|
var name string
|
||||||
|
if name = republicOfChinaEraName[0]; len(token.TValue) < 3 {
|
||||||
|
name = republicOfChinaEraName[1]
|
||||||
|
}
|
||||||
|
if year < 0 {
|
||||||
|
name += republicOfChinaEraName[2]
|
||||||
|
}
|
||||||
|
nf.result += name
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToUpper(token.TValue), "E") {
|
||||||
|
year := nf.t.Year() - republicOfChinaYear.Year() + 1
|
||||||
|
if year < 0 {
|
||||||
|
year = republicOfChinaYear.Year() - nf.t.Year()
|
||||||
|
}
|
||||||
|
if year == 1 && nf.useGannen {
|
||||||
|
nf.result += "\u5143"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(token.TValue) == 1 && !nf.useGannen {
|
||||||
|
nf.result += strconv.Itoa(year)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// yearsHandler will be handling years in the date and times types tokens for a
|
||||||
|
// number format expression.
|
||||||
|
func (nf *numberFormat) yearsHandler(token nfp.Token) {
|
||||||
|
langInfo, _ := getSupportedLanguageInfo(nf.localCode)
|
||||||
|
if strings.Contains(strings.ToUpper(token.TValue), "Y") {
|
||||||
|
year := nf.t.Year()
|
||||||
|
if nf.opts != nil && nf.opts.CultureInfo == CultureNameKoKR {
|
||||||
|
year += 2333
|
||||||
|
}
|
||||||
|
if len(token.TValue) <= 2 {
|
||||||
|
nf.result += strconv.Itoa(year)[2:]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nf.result += strconv.Itoa(year)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if inStrSlice(langInfo.tags, "zh-TW", false) != -1 ||
|
||||||
|
nf.opts != nil && nf.opts.CultureInfo == CultureNameZhTW {
|
||||||
|
nf.republicOfChinaYearHandler(token, langInfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if inStrSlice(langInfo.tags, "ja-JP", false) != -1 ||
|
||||||
|
nf.opts != nil && nf.opts.CultureInfo == CultureNameJaJP {
|
||||||
|
nf.japaneseYearHandler(token, langInfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToUpper(token.TValue), "E") {
|
||||||
|
nf.result += strconv.Itoa(nf.t.Year())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// daysHandler will be handling days in the date and times types tokens for a
|
// daysHandler will be handling days in the date and times types tokens for a
|
||||||
// number format expression.
|
// number format expression.
|
||||||
func (nf *numberFormat) daysHandler(token nfp.Token) {
|
func (nf *numberFormat) daysHandler(token nfp.Token) {
|
||||||
|
|
|
@ -289,6 +289,20 @@ func TestNumFmt(t *testing.T) {
|
||||||
{"43543.503206018519", "[$-401]mmmm dd yyyy h:mm AM/PM aaa", "\u0645\u0627\u0631\u0633 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"},
|
{"43543.503206018519", "[$-401]mmmm dd yyyy h:mm AM/PM aaa", "\u0645\u0627\u0631\u0633 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"},
|
||||||
{"43543.503206018519", "[$-401]mmmmm dd yyyy h:mm AM/PM ddd", "\u0645 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"},
|
{"43543.503206018519", "[$-401]mmmmm dd yyyy h:mm AM/PM ddd", "\u0645 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"},
|
||||||
{"43543.503206018519", "[$-401]mmmmmm dd yyyy h:mm AM/PM dddd", "\u0645\u0627\u0631\u0633 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"},
|
{"43543.503206018519", "[$-401]mmmmmm dd yyyy h:mm AM/PM dddd", "\u0645\u0627\u0631\u0633 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"},
|
||||||
|
{"43466.189571759256", "[$-404]g\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u5e74\u0031\u6708\u0031\u65e5"},
|
||||||
|
{"43466.189571759256", "[$-404]e\"年\"m\"月\"d\"日\";@", "\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"},
|
||||||
|
{"43466.189571759256", "[$-404]ge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"},
|
||||||
|
{"43466.189571759256", "[$-404]gge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"},
|
||||||
|
{"43466.189571759256", "[$-404]ggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"},
|
||||||
|
{"43466.189571759256", "[$-404]gggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"},
|
||||||
|
{"4385.5083333333332", "[$-404]ge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"},
|
||||||
|
{"4385.5083333333332", "[$-404]gge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"},
|
||||||
|
{"4385.5083333333332", "[$-404]ggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"},
|
||||||
|
{"4385.5083333333332", "[$-404]gggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"},
|
||||||
|
{"123", "[$-404]ge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"},
|
||||||
|
{"123", "[$-404]gge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"},
|
||||||
|
{"123", "[$-404]ggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"},
|
||||||
|
{"123", "[$-404]gggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"},
|
||||||
{"44562.189571759256", "[$-1010401]mmm dd yyyy h:mm AM/PM", "\u064A\u0646\u0627\u064A\u0631 01 2022 4:32 \u0635"},
|
{"44562.189571759256", "[$-1010401]mmm dd yyyy h:mm AM/PM", "\u064A\u0646\u0627\u064A\u0631 01 2022 4:32 \u0635"},
|
||||||
{"44562.189571759256", "[$-1010401]mmmm dd yyyy h:mm AM/PM", "\u064A\u0646\u0627\u064A\u0631 01 2022 4:32 \u0635"},
|
{"44562.189571759256", "[$-1010401]mmmm dd yyyy h:mm AM/PM", "\u064A\u0646\u0627\u064A\u0631 01 2022 4:32 \u0635"},
|
||||||
{"44562.189571759256", "[$-1010401]mmmmm dd yyyy h:mm AM/PM", "\u064A 01 2022 4:32 \u0635"},
|
{"44562.189571759256", "[$-1010401]mmmmm dd yyyy h:mm AM/PM", "\u064A 01 2022 4:32 \u0635"},
|
||||||
|
@ -2722,6 +2736,9 @@ func TestNumFmt(t *testing.T) {
|
||||||
{"44835.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM aaa", "\u0e15 01 2022 4:32 AM \u0E2A."},
|
{"44835.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM aaa", "\u0e15 01 2022 4:32 AM \u0E2A."},
|
||||||
{"44866.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM ddd", "\u0e1e 01 2022 4:32 AM \u0E2D."},
|
{"44866.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM ddd", "\u0e1e 01 2022 4:32 AM \u0E2D."},
|
||||||
{"44896.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM dddd", "\u0e18 01 2022 4:32 AM \u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35"},
|
{"44896.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM dddd", "\u0e18 01 2022 4:32 AM \u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35"},
|
||||||
|
{"100", "g\"年\"m\"月\"d\"日\";@", "年4月9日"},
|
||||||
|
{"100", "e\"年\"m\"月\"d\"日\";@", "1900年4月9日"},
|
||||||
|
{"100", "ge\"年\"m\"月\"d\"日\";@", "1900年4月9日"},
|
||||||
{"100", "[$-411]ge\"年\"m\"月\"d\"日\";@", "1900年4月9日"},
|
{"100", "[$-411]ge\"年\"m\"月\"d\"日\";@", "1900年4月9日"},
|
||||||
{"43709", "[$-411]ge\"年\"m\"月\"d\"日\";@", "R1年9月1日"},
|
{"43709", "[$-411]ge\"年\"m\"月\"d\"日\";@", "R1年9月1日"},
|
||||||
{"43709", "[$-411]gge\"年\"m\"月\"d\"日\";@", "\u4EE41年9月1日"},
|
{"43709", "[$-411]gge\"年\"m\"月\"d\"日\";@", "\u4EE41年9月1日"},
|
||||||
|
|
25
picture.go
25
picture.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
// PictureInsertType defines the type of the picture has been inserted into the
|
// PictureInsertType defines the type of the picture has been inserted into the
|
||||||
// worksheet.
|
// worksheet.
|
||||||
type PictureInsertType int
|
type PictureInsertType byte
|
||||||
|
|
||||||
// Insert picture types.
|
// Insert picture types.
|
||||||
const (
|
const (
|
||||||
|
@ -295,6 +295,16 @@ func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addSheetLegacyDrawingHF provides a function to add legacy drawing
|
||||||
|
// header/footer element to xl/worksheets/sheet%d.xml by given
|
||||||
|
// worksheet name and relationship index.
|
||||||
|
func (f *File) addSheetLegacyDrawingHF(sheet string, rID int) {
|
||||||
|
ws, _ := f.workSheetReader(sheet)
|
||||||
|
ws.LegacyDrawingHF = &xlsxLegacyDrawingHF{
|
||||||
|
RID: "rId" + strconv.Itoa(rID),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// addSheetDrawing provides a function to add drawing element to
|
// addSheetDrawing provides a function to add drawing element to
|
||||||
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
|
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
|
||||||
func (f *File) addSheetDrawing(sheet string, rID int) {
|
func (f *File) addSheetDrawing(sheet string, rID int) {
|
||||||
|
@ -556,10 +566,11 @@ func (f *File) DeletePicture(sheet, cell string) error {
|
||||||
}
|
}
|
||||||
drawingXML := strings.ReplaceAll(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl")
|
drawingXML := strings.ReplaceAll(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl")
|
||||||
drawingRels := "xl/drawings/_rels/" + filepath.Base(drawingXML) + ".rels"
|
drawingRels := "xl/drawings/_rels/" + filepath.Base(drawingXML) + ".rels"
|
||||||
rID, err := f.deleteDrawing(col, row, drawingXML, "Pic")
|
rIDs, err := f.deleteDrawing(col, row, drawingXML, "Pic")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, rID := range rIDs {
|
||||||
rels := f.getDrawingRelationships(drawingRels, rID)
|
rels := f.getDrawingRelationships(drawingRels, rID)
|
||||||
if rels == nil {
|
if rels == nil {
|
||||||
return err
|
return err
|
||||||
|
@ -567,12 +578,15 @@ func (f *File) DeletePicture(sheet, cell string) error {
|
||||||
var used bool
|
var used bool
|
||||||
checkPicRef := func(k, v interface{}) bool {
|
checkPicRef := func(k, v interface{}) bool {
|
||||||
if strings.Contains(k.(string), "xl/drawings/_rels/drawing") {
|
if strings.Contains(k.(string), "xl/drawings/_rels/drawing") {
|
||||||
|
if k.(string) == drawingRels {
|
||||||
|
return true
|
||||||
|
}
|
||||||
r, err := f.relsReader(k.(string))
|
r, err := f.relsReader(k.(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for _, rel := range r.Relationships {
|
for _, rel := range r.Relationships {
|
||||||
if rel.ID != rels.ID && rel.Type == SourceRelationshipImage &&
|
if rel.Type == SourceRelationshipImage &&
|
||||||
filepath.Base(rel.Target) == filepath.Base(rels.Target) {
|
filepath.Base(rel.Target) == filepath.Base(rels.Target) {
|
||||||
used = true
|
used = true
|
||||||
}
|
}
|
||||||
|
@ -586,6 +600,7 @@ func (f *File) DeletePicture(sheet, cell string) error {
|
||||||
f.Pkg.Delete(strings.Replace(rels.Target, "../", "xl/", -1))
|
f.Pkg.Delete(strings.Replace(rels.Target, "../", "xl/", -1))
|
||||||
}
|
}
|
||||||
f.deleteDrawingRels(drawingRels, rID)
|
f.deleteDrawingRels(drawingRels, rID)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,9 +334,9 @@ func TestDeletePicture(t *testing.T) {
|
||||||
f, err = OpenFile(filepath.Join("test", "TestDeletePicture.xlsx"))
|
f, err = OpenFile(filepath.Join("test", "TestDeletePicture.xlsx"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Test delete same picture on different worksheet, the images should be removed
|
// Test delete same picture on different worksheet, the images should be removed
|
||||||
assert.NoError(t, f.DeletePicture("Sheet1", "F10"))
|
assert.NoError(t, f.DeletePicture("Sheet1", "F20"))
|
||||||
assert.NoError(t, f.DeletePicture("Sheet2", "F1"))
|
|
||||||
assert.NoError(t, f.DeletePicture("Sheet1", "I20"))
|
assert.NoError(t, f.DeletePicture("Sheet1", "I20"))
|
||||||
|
assert.NoError(t, f.DeletePicture("Sheet2", "F1"))
|
||||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeletePicture2.xlsx")))
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestDeletePicture2.xlsx")))
|
||||||
|
|
||||||
// Test delete picture on not exists worksheet
|
// Test delete picture on not exists worksheet
|
||||||
|
@ -364,6 +364,14 @@ func TestDeletePicture(t *testing.T) {
|
||||||
assert.NoError(t, f.DeletePicture("Sheet2", "F1"))
|
assert.NoError(t, f.DeletePicture("Sheet2", "F1"))
|
||||||
assert.NoError(t, f.Close())
|
assert.NoError(t, f.Close())
|
||||||
|
|
||||||
|
f, err = OpenFile(filepath.Join("test", "TestDeletePicture.xlsx"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Test delete picture without drawing relationships
|
||||||
|
f.Relationships.Delete("xl/drawings/_rels/drawing1.xml.rels")
|
||||||
|
f.Pkg.Delete("xl/drawings/_rels/drawing1.xml.rels")
|
||||||
|
assert.NoError(t, f.DeletePicture("Sheet1", "I20"))
|
||||||
|
assert.NoError(t, f.Close())
|
||||||
|
|
||||||
f = NewFile()
|
f = NewFile()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, f.AddPicture("Sheet1", "A1", filepath.Join("test", "images", "excel.jpg"), nil))
|
assert.NoError(t, f.AddPicture("Sheet1", "A1", filepath.Join("test", "images", "excel.jpg"), nil))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -899,14 +899,27 @@ func (f *File) getPivotTable(sheet, pivotTableXML, pivotCacheRels string) (Pivot
|
||||||
opts.ShowLastColumn = si.ShowLastColumn
|
opts.ShowLastColumn = si.ShowLastColumn
|
||||||
opts.PivotTableStyleName = si.Name
|
opts.PivotTableStyleName = si.Name
|
||||||
}
|
}
|
||||||
order, err := f.getTableFieldsOrder(&opts)
|
if err = f.getPivotTableDataRange(&opts); err != nil {
|
||||||
if err != nil {
|
|
||||||
return opts, err
|
return opts, err
|
||||||
}
|
}
|
||||||
f.extractPivotTableFields(order, pt, &opts)
|
f.extractPivotTableFields(pc.getPivotCacheFieldsName(), pt, &opts)
|
||||||
return opts, err
|
return opts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPivotCacheFieldsName returns pivot table fields name list by order from
|
||||||
|
// pivot cache fields.
|
||||||
|
func (pc *xlsxPivotCacheDefinition) getPivotCacheFieldsName() []string {
|
||||||
|
var order []string
|
||||||
|
if pc.CacheFields != nil {
|
||||||
|
for _, cf := range pc.CacheFields.CacheField {
|
||||||
|
if cf != nil {
|
||||||
|
order = append(order, cf.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
// pivotTableReader provides a function to get the pointer to the structure
|
// pivotTableReader provides a function to get the pointer to the structure
|
||||||
// after deserialization of xl/pivotTables/pivotTable%d.xml.
|
// after deserialization of xl/pivotTables/pivotTable%d.xml.
|
||||||
func (f *File) pivotTableReader(path string) (*xlsxPivotTableDefinition, error) {
|
func (f *File) pivotTableReader(path string) (*xlsxPivotTableDefinition, error) {
|
||||||
|
|
|
@ -516,7 +516,7 @@ func TestDeleteWorkbookPivotCache(t *testing.T) {
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
// Test delete workbook pivot table cache with unsupported workbook charset
|
// Test delete workbook pivot table cache with unsupported workbook charset
|
||||||
f.WorkBook = nil
|
f.WorkBook = nil
|
||||||
f.Pkg.Store("xl/workbook.xml", MacintoshCyrillicCharset)
|
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||||
assert.EqualError(t, f.deleteWorkbookPivotCache(PivotTableOptions{pivotCacheXML: "pivotCache/pivotCacheDefinition1.xml"}), "XML syntax error on line 1: invalid UTF-8")
|
assert.EqualError(t, f.deleteWorkbookPivotCache(PivotTableOptions{pivotCacheXML: "pivotCache/pivotCacheDefinition1.xml"}), "XML syntax error on line 1: invalid UTF-8")
|
||||||
|
|
||||||
// Test delete workbook pivot table cache with unsupported workbook relationships charset
|
// Test delete workbook pivot table cache with unsupported workbook relationships charset
|
||||||
|
|
14
rows.go
14
rows.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mohae/deepcopy"
|
"github.com/tiendc/go-deepcopy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// duplicateHelperFunc defines functions to duplicate helper.
|
// duplicateHelperFunc defines functions to duplicate helper.
|
||||||
|
@ -653,7 +653,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
||||||
|
|
||||||
for i, r := range ws.SheetData.Row {
|
for i, r := range ws.SheetData.Row {
|
||||||
if r.R == row {
|
if r.R == row {
|
||||||
rowCopy = deepcopy.Copy(ws.SheetData.Row[i]).(xlsxRow)
|
deepcopy.Copy(&rowCopy, ws.SheetData.Row[i])
|
||||||
ok = true
|
ok = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -729,7 +729,8 @@ func (f *File) duplicateConditionalFormat(ws *xlsxWorksheet, sheet string, row,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(SQRef) > 0 {
|
if len(SQRef) > 0 {
|
||||||
cfCopy := deepcopy.Copy(*cf).(xlsxConditionalFormatting)
|
var cfCopy xlsxConditionalFormatting
|
||||||
|
deepcopy.Copy(&cfCopy, *cf)
|
||||||
cfCopy.SQRef = strings.Join(SQRef, " ")
|
cfCopy.SQRef = strings.Join(SQRef, " ")
|
||||||
cfs = append(cfs, &cfCopy)
|
cfs = append(cfs, &cfCopy)
|
||||||
}
|
}
|
||||||
|
@ -759,7 +760,8 @@ func (f *File) duplicateDataValidations(ws *xlsxWorksheet, sheet string, row, ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(SQRef) > 0 {
|
if len(SQRef) > 0 {
|
||||||
dvCopy := deepcopy.Copy(*dv).(xlsxDataValidation)
|
var dvCopy xlsxDataValidation
|
||||||
|
deepcopy.Copy(&dvCopy, *dv)
|
||||||
dvCopy.Sqref = strings.Join(SQRef, " ")
|
dvCopy.Sqref = strings.Join(SQRef, " ")
|
||||||
dvs = append(dvs, &dvCopy)
|
dvs = append(dvs, &dvCopy)
|
||||||
}
|
}
|
||||||
|
|
4
shape.go
4
shape.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
94
sheet.go
94
sheet.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -27,7 +27,23 @@ import (
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/mohae/deepcopy"
|
"github.com/tiendc/go-deepcopy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IgnoredErrorsType is the type of ignored errors.
|
||||||
|
type IgnoredErrorsType byte
|
||||||
|
|
||||||
|
// Ignored errors types enumeration.
|
||||||
|
const (
|
||||||
|
IgnoredErrorsEvalError = iota
|
||||||
|
IgnoredErrorsTwoDigitTextYear
|
||||||
|
IgnoredErrorsNumberStoredAsText
|
||||||
|
IgnoredErrorsFormula
|
||||||
|
IgnoredErrorsFormulaRange
|
||||||
|
IgnoredErrorsUnlockedFormula
|
||||||
|
IgnoredErrorsEmptyCellReference
|
||||||
|
IgnoredErrorsListDataValidation
|
||||||
|
IgnoredErrorsCalculatedColumn
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSheet provides the function to create a new sheet by given a worksheet
|
// NewSheet provides the function to create a new sheet by given a worksheet
|
||||||
|
@ -124,7 +140,8 @@ func (f *File) mergeExpandedCols(ws *xlsxWorksheet) {
|
||||||
Width: ws.Cols.Col[i-1].Width,
|
Width: ws.Cols.Col[i-1].Width,
|
||||||
}, ws.Cols.Col[i]); i++ {
|
}, ws.Cols.Col[i]); i++ {
|
||||||
}
|
}
|
||||||
column := deepcopy.Copy(ws.Cols.Col[left]).(xlsxCol)
|
var column xlsxCol
|
||||||
|
deepcopy.Copy(&column, ws.Cols.Col[left])
|
||||||
if left < i-1 {
|
if left < i-1 {
|
||||||
column.Max = ws.Cols.Col[i-1].Min
|
column.Max = ws.Cols.Col[i-1].Min
|
||||||
}
|
}
|
||||||
|
@ -750,7 +767,8 @@ func (f *File) copySheet(from, to int) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
|
worksheet := &xlsxWorksheet{}
|
||||||
|
deepcopy.Copy(worksheet, sheet)
|
||||||
toSheetID := strconv.Itoa(f.getSheetID(f.GetSheetName(to)))
|
toSheetID := strconv.Itoa(f.getSheetID(f.GetSheetName(to)))
|
||||||
sheetXMLPath := "xl/worksheets/sheet" + toSheetID + ".xml"
|
sheetXMLPath := "xl/worksheets/sheet" + toSheetID + ".xml"
|
||||||
if len(worksheet.SheetViews.SheetView) > 0 {
|
if len(worksheet.SheetViews.SheetView) > 0 {
|
||||||
|
@ -1239,7 +1257,7 @@ func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
|
||||||
// |
|
// |
|
||||||
// &F | Current workbook's file name
|
// &F | Current workbook's file name
|
||||||
// |
|
// |
|
||||||
// &G | Drawing object as background (Not support currently)
|
// &G | Drawing object as background (Use AddHeaderFooterImage)
|
||||||
// |
|
// |
|
||||||
// &H | Shadow text format
|
// &H | Shadow text format
|
||||||
// |
|
// |
|
||||||
|
@ -1609,8 +1627,7 @@ func (f *File) SetPageLayout(sheet string, opts *PageLayoutOptions) error {
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ws.setPageSetUp(opts)
|
return ws.setPageSetUp(opts)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPageSetUp initialize page setup settings for the worksheet if which not
|
// newPageSetUp initialize page setup settings for the worksheet if which not
|
||||||
|
@ -1622,12 +1639,15 @@ func (ws *xlsxWorksheet) newPageSetUp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setPageSetUp set page setup settings for the worksheet by given options.
|
// setPageSetUp set page setup settings for the worksheet by given options.
|
||||||
func (ws *xlsxWorksheet) setPageSetUp(opts *PageLayoutOptions) {
|
func (ws *xlsxWorksheet) setPageSetUp(opts *PageLayoutOptions) error {
|
||||||
if opts.Size != nil {
|
if opts.Size != nil {
|
||||||
ws.newPageSetUp()
|
ws.newPageSetUp()
|
||||||
ws.PageSetUp.PaperSize = opts.Size
|
ws.PageSetUp.PaperSize = opts.Size
|
||||||
}
|
}
|
||||||
if opts.Orientation != nil && (*opts.Orientation == "portrait" || *opts.Orientation == "landscape") {
|
if opts.Orientation != nil {
|
||||||
|
if inStrSlice(supportedPageOrientation, *opts.Orientation, true) == -1 {
|
||||||
|
return newInvalidPageLayoutValueError("Orientation", *opts.Orientation, strings.Join(supportedPageOrientation, ", "))
|
||||||
|
}
|
||||||
ws.newPageSetUp()
|
ws.newPageSetUp()
|
||||||
ws.PageSetUp.Orientation = *opts.Orientation
|
ws.PageSetUp.Orientation = *opts.Orientation
|
||||||
}
|
}
|
||||||
|
@ -1636,7 +1656,10 @@ func (ws *xlsxWorksheet) setPageSetUp(opts *PageLayoutOptions) {
|
||||||
ws.PageSetUp.FirstPageNumber = strconv.Itoa(int(*opts.FirstPageNumber))
|
ws.PageSetUp.FirstPageNumber = strconv.Itoa(int(*opts.FirstPageNumber))
|
||||||
ws.PageSetUp.UseFirstPageNumber = true
|
ws.PageSetUp.UseFirstPageNumber = true
|
||||||
}
|
}
|
||||||
if opts.AdjustTo != nil && 10 <= *opts.AdjustTo && *opts.AdjustTo <= 400 {
|
if opts.AdjustTo != nil {
|
||||||
|
if *opts.AdjustTo < 10 || 400 < *opts.AdjustTo {
|
||||||
|
return ErrPageSetupAdjustTo
|
||||||
|
}
|
||||||
ws.newPageSetUp()
|
ws.newPageSetUp()
|
||||||
ws.PageSetUp.Scale = int(*opts.AdjustTo)
|
ws.PageSetUp.Scale = int(*opts.AdjustTo)
|
||||||
}
|
}
|
||||||
|
@ -1652,13 +1675,21 @@ func (ws *xlsxWorksheet) setPageSetUp(opts *PageLayoutOptions) {
|
||||||
ws.newPageSetUp()
|
ws.newPageSetUp()
|
||||||
ws.PageSetUp.BlackAndWhite = *opts.BlackAndWhite
|
ws.PageSetUp.BlackAndWhite = *opts.BlackAndWhite
|
||||||
}
|
}
|
||||||
|
if opts.PageOrder != nil {
|
||||||
|
if inStrSlice(supportedPageOrder, *opts.PageOrder, true) == -1 {
|
||||||
|
return newInvalidPageLayoutValueError("PageOrder", *opts.PageOrder, strings.Join(supportedPageOrder, ", "))
|
||||||
|
}
|
||||||
|
ws.newPageSetUp()
|
||||||
|
ws.PageSetUp.PageOrder = *opts.PageOrder
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPageLayout provides a function to gets worksheet page layout.
|
// GetPageLayout provides a function to gets worksheet page layout.
|
||||||
func (f *File) GetPageLayout(sheet string) (PageLayoutOptions, error) {
|
func (f *File) GetPageLayout(sheet string) (PageLayoutOptions, error) {
|
||||||
opts := PageLayoutOptions{
|
opts := PageLayoutOptions{
|
||||||
Size: intPtr(0),
|
Size: intPtr(0),
|
||||||
Orientation: stringPtr("portrait"),
|
Orientation: stringPtr(supportedPageOrientation[0]),
|
||||||
FirstPageNumber: uintPtr(1),
|
FirstPageNumber: uintPtr(1),
|
||||||
AdjustTo: uintPtr(100),
|
AdjustTo: uintPtr(100),
|
||||||
}
|
}
|
||||||
|
@ -1686,6 +1717,9 @@ func (f *File) GetPageLayout(sheet string) (PageLayoutOptions, error) {
|
||||||
opts.FitToWidth = ws.PageSetUp.FitToWidth
|
opts.FitToWidth = ws.PageSetUp.FitToWidth
|
||||||
}
|
}
|
||||||
opts.BlackAndWhite = boolPtr(ws.PageSetUp.BlackAndWhite)
|
opts.BlackAndWhite = boolPtr(ws.PageSetUp.BlackAndWhite)
|
||||||
|
if ws.PageSetUp.PageOrder != "" {
|
||||||
|
opts.PageOrder = stringPtr(ws.PageSetUp.PageOrder)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return opts, err
|
return opts, err
|
||||||
}
|
}
|
||||||
|
@ -2008,7 +2042,7 @@ func (f *File) relsReader(path string) (*xlsxRelationships, error) {
|
||||||
// fillSheetData ensures there are enough rows, and columns in the chosen
|
// fillSheetData ensures there are enough rows, and columns in the chosen
|
||||||
// row to accept data. Missing rows are backfilled and given their row number
|
// row to accept data. Missing rows are backfilled and given their row number
|
||||||
// Uses the last populated row as a hint for the size of the next row to add
|
// Uses the last populated row as a hint for the size of the next row to add
|
||||||
func (ws *xlsxWorksheet) prepareSheetXML(col int, row int) {
|
func (ws *xlsxWorksheet) prepareSheetXML(col, row int) {
|
||||||
rowCount := len(ws.SheetData.Row)
|
rowCount := len(ws.SheetData.Row)
|
||||||
sizeHint := 0
|
sizeHint := 0
|
||||||
var ht *float64
|
var ht *float64
|
||||||
|
@ -2054,7 +2088,7 @@ func (ws *xlsxWorksheet) makeContiguousColumns(fromRow, toRow, colCount int) {
|
||||||
// of used cells in the worksheet. The range reference is set using the A1
|
// of used cells in the worksheet. The range reference is set using the A1
|
||||||
// reference style(e.g., "A1:D5"). Passing an empty range reference will remove
|
// reference style(e.g., "A1:D5"). Passing an empty range reference will remove
|
||||||
// the used range of the worksheet.
|
// the used range of the worksheet.
|
||||||
func (f *File) SetSheetDimension(sheet string, rangeRef string) error {
|
func (f *File) SetSheetDimension(sheet, rangeRef string) error {
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2097,3 +2131,35 @@ func (f *File) GetSheetDimension(sheet string) (string, error) {
|
||||||
}
|
}
|
||||||
return ref, err
|
return ref, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddIgnoredErrors provides the method to ignored error for a range of cells.
|
||||||
|
func (f *File) AddIgnoredErrors(sheet, rangeRef string, ignoredErrorsType IgnoredErrorsType) error {
|
||||||
|
ws, err := f.workSheetReader(sheet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rangeRef == "" {
|
||||||
|
return ErrParameterInvalid
|
||||||
|
}
|
||||||
|
if ws.IgnoredErrors == nil {
|
||||||
|
ws.IgnoredErrors = &xlsxIgnoredErrors{}
|
||||||
|
}
|
||||||
|
ie := map[IgnoredErrorsType]xlsxIgnoredError{
|
||||||
|
IgnoredErrorsEvalError: {Sqref: rangeRef, EvalError: true},
|
||||||
|
IgnoredErrorsTwoDigitTextYear: {Sqref: rangeRef, TwoDigitTextYear: true},
|
||||||
|
IgnoredErrorsNumberStoredAsText: {Sqref: rangeRef, NumberStoredAsText: true},
|
||||||
|
IgnoredErrorsFormula: {Sqref: rangeRef, Formula: true},
|
||||||
|
IgnoredErrorsFormulaRange: {Sqref: rangeRef, FormulaRange: true},
|
||||||
|
IgnoredErrorsUnlockedFormula: {Sqref: rangeRef, UnlockedFormula: true},
|
||||||
|
IgnoredErrorsEmptyCellReference: {Sqref: rangeRef, EmptyCellReference: true},
|
||||||
|
IgnoredErrorsListDataValidation: {Sqref: rangeRef, ListDataValidation: true},
|
||||||
|
IgnoredErrorsCalculatedColumn: {Sqref: rangeRef, CalculatedColumn: true},
|
||||||
|
}[ignoredErrorsType]
|
||||||
|
for _, val := range ws.IgnoredErrors.IgnoredError {
|
||||||
|
if reflect.DeepEqual(val, ie) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws.IgnoredErrors.IgnoredError = append(ws.IgnoredErrors.IgnoredError, ie)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -210,6 +210,7 @@ func TestSetPageLayout(t *testing.T) {
|
||||||
FitToHeight: intPtr(2),
|
FitToHeight: intPtr(2),
|
||||||
FitToWidth: intPtr(2),
|
FitToWidth: intPtr(2),
|
||||||
BlackAndWhite: boolPtr(true),
|
BlackAndWhite: boolPtr(true),
|
||||||
|
PageOrder: stringPtr("overThenDown"),
|
||||||
}
|
}
|
||||||
assert.NoError(t, f.SetPageLayout("Sheet1", &expected))
|
assert.NoError(t, f.SetPageLayout("Sheet1", &expected))
|
||||||
opts, err := f.GetPageLayout("Sheet1")
|
opts, err := f.GetPageLayout("Sheet1")
|
||||||
|
@ -219,6 +220,16 @@ func TestSetPageLayout(t *testing.T) {
|
||||||
assert.EqualError(t, f.SetPageLayout("SheetN", nil), "sheet SheetN does not exist")
|
assert.EqualError(t, f.SetPageLayout("SheetN", nil), "sheet SheetN does not exist")
|
||||||
// Test set page layout with invalid sheet name
|
// Test set page layout with invalid sheet name
|
||||||
assert.EqualError(t, f.SetPageLayout("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
assert.EqualError(t, f.SetPageLayout("Sheet:1", nil), ErrSheetNameInvalid.Error())
|
||||||
|
// Test set page layout with invalid parameters
|
||||||
|
assert.EqualError(t, f.SetPageLayout("Sheet1", &PageLayoutOptions{
|
||||||
|
AdjustTo: uintPtr(5),
|
||||||
|
}), "adjust to value must be between 10 and 400")
|
||||||
|
assert.EqualError(t, f.SetPageLayout("Sheet1", &PageLayoutOptions{
|
||||||
|
Orientation: stringPtr("x"),
|
||||||
|
}), "invalid Orientation value \"x\", acceptable value should be one of portrait, landscape")
|
||||||
|
assert.EqualError(t, f.SetPageLayout("Sheet1", &PageLayoutOptions{
|
||||||
|
PageOrder: stringPtr("x"),
|
||||||
|
}), "invalid PageOrder value \"x\", acceptable value should be one of overThenDown, downThenOver")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPageLayout(t *testing.T) {
|
func TestGetPageLayout(t *testing.T) {
|
||||||
|
@ -580,7 +591,7 @@ func TestMoveSheet(t *testing.T) {
|
||||||
|
|
||||||
// Test move sheet with unsupported workbook charset
|
// Test move sheet with unsupported workbook charset
|
||||||
f.WorkBook = nil
|
f.WorkBook = nil
|
||||||
f.Pkg.Store("xl/workbook.xml", MacintoshCyrillicCharset)
|
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||||
assert.EqualError(t, f.MoveSheet("Sheet2", "Sheet1"), "XML syntax error on line 1: invalid UTF-8")
|
assert.EqualError(t, f.MoveSheet("Sheet2", "Sheet1"), "XML syntax error on line 1: invalid UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +675,7 @@ func BenchmarkNewSheet(b *testing.B) {
|
||||||
func newSheetWithSet() {
|
func newSheetWithSet() {
|
||||||
file := NewFile()
|
file := NewFile()
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
_ = file.SetCellInt("Sheet1", "A"+strconv.Itoa(i+1), i)
|
_ = file.SetCellInt("Sheet1", "A"+strconv.Itoa(i+1), int64(i))
|
||||||
}
|
}
|
||||||
file = nil
|
file = nil
|
||||||
}
|
}
|
||||||
|
@ -680,7 +691,7 @@ func BenchmarkFile_SaveAs(b *testing.B) {
|
||||||
func newSheetWithSave() {
|
func newSheetWithSave() {
|
||||||
file := NewFile()
|
file := NewFile()
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
_ = file.SetCellInt("Sheet1", "A"+strconv.Itoa(i+1), i)
|
_ = file.SetCellInt("Sheet1", "A"+strconv.Itoa(i+1), int64(i))
|
||||||
}
|
}
|
||||||
_ = file.Save()
|
_ = file.Save()
|
||||||
}
|
}
|
||||||
|
@ -810,3 +821,23 @@ func TestSheetDimension(t *testing.T) {
|
||||||
assert.Empty(t, dimension)
|
assert.Empty(t, dimension)
|
||||||
assert.EqualError(t, err, "sheet SheetN does not exist")
|
assert.EqualError(t, err, "sheet SheetN does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddIgnoredErrors(t *testing.T) {
|
||||||
|
f := NewFile()
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsEvalError))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsEvalError))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsTwoDigitTextYear))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsNumberStoredAsText))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsFormula))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsFormulaRange))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsUnlockedFormula))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsEmptyCellReference))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsListDataValidation))
|
||||||
|
assert.NoError(t, f.AddIgnoredErrors("Sheet1", "A1", IgnoredErrorsCalculatedColumn))
|
||||||
|
|
||||||
|
assert.Equal(t, ErrSheetNotExist{"SheetN"}, f.AddIgnoredErrors("SheetN", "A1", IgnoredErrorsEvalError))
|
||||||
|
assert.Equal(t, ErrParameterInvalid, f.AddIgnoredErrors("Sheet1", "", IgnoredErrorsEvalError))
|
||||||
|
|
||||||
|
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddIgnoredErrors.xlsx")))
|
||||||
|
assert.NoError(t, f.Close())
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ func (ws *xlsxWorksheet) prepareSheetPr() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setSheetOutlinePr set worksheet outline properties by given options.
|
// setSheetOutlineProps set worksheet outline properties by given options.
|
||||||
func (ws *xlsxWorksheet) setSheetOutlineProps(opts *SheetPropsOptions) {
|
func (ws *xlsxWorksheet) setSheetOutlineProps(opts *SheetPropsOptions) {
|
||||||
prepareOutlinePr := func(ws *xlsxWorksheet) {
|
prepareOutlinePr := func(ws *xlsxWorksheet) {
|
||||||
ws.prepareSheetPr()
|
ws.prepareSheetPr()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -597,7 +597,7 @@ func TestAddWorkbookSlicerCache(t *testing.T) {
|
||||||
// Test add a workbook slicer cache with unsupported charset workbook
|
// Test add a workbook slicer cache with unsupported charset workbook
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
f.WorkBook = nil
|
f.WorkBook = nil
|
||||||
f.Pkg.Store("xl/workbook.xml", MacintoshCyrillicCharset)
|
f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
|
||||||
assert.EqualError(t, f.addWorkbookSlicerCache(1, ExtURISlicerCachesX15), "XML syntax error on line 1: invalid UTF-8")
|
assert.EqualError(t, f.addWorkbookSlicerCache(1, ExtURISlicerCachesX15), "XML syntax error on line 1: invalid UTF-8")
|
||||||
assert.NoError(t, f.Close())
|
assert.NoError(t, f.Close())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
84
stream.go
84
stream.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ type StreamWriter struct {
|
||||||
Sheet string
|
Sheet string
|
||||||
SheetID int
|
SheetID int
|
||||||
sheetWritten bool
|
sheetWritten bool
|
||||||
cols strings.Builder
|
|
||||||
worksheet *xlsxWorksheet
|
worksheet *xlsxWorksheet
|
||||||
rawData bufferedWriter
|
rawData bufferedWriter
|
||||||
rows int
|
rows int
|
||||||
|
@ -413,16 +412,18 @@ func (sw *StreamWriter) SetRow(cell string, values []interface{}, opts ...RowOpt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c := xlsxC{R: ref, S: options.StyleID}
|
c := xlsxC{R: ref, S: sw.worksheet.prepareCellStyle(col, row, options.StyleID)}
|
||||||
|
var s int
|
||||||
if v, ok := val.(Cell); ok {
|
if v, ok := val.(Cell); ok {
|
||||||
c.S = v.StyleID
|
s, val = v.StyleID, v.Value
|
||||||
val = v.Value
|
|
||||||
setCellFormula(&c, v.Formula)
|
setCellFormula(&c, v.Formula)
|
||||||
} else if v, ok := val.(*Cell); ok && v != nil {
|
} else if v, ok := val.(*Cell); ok && v != nil {
|
||||||
c.S = v.StyleID
|
s, val = v.StyleID, v.Value
|
||||||
val = v.Value
|
|
||||||
setCellFormula(&c, v.Formula)
|
setCellFormula(&c, v.Formula)
|
||||||
}
|
}
|
||||||
|
if s > 0 {
|
||||||
|
c.S = s
|
||||||
|
}
|
||||||
if err = sw.setCellValFunc(&c, val); err != nil {
|
if err = sw.setCellValFunc(&c, val); err != nil {
|
||||||
_, _ = sw.rawData.WriteString(`</row>`)
|
_, _ = sw.rawData.WriteString(`</row>`)
|
||||||
return err
|
return err
|
||||||
|
@ -433,6 +434,33 @@ func (sw *StreamWriter) SetRow(cell string, values []interface{}, opts ...RowOpt
|
||||||
return sw.rawData.Sync()
|
return sw.rawData.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetColStyle provides a function to set the style of a single column or
|
||||||
|
// multiple columns for the StreamWriter. Note that you must call
|
||||||
|
// the 'SetColStyle' function before the 'SetRow' function. For example set
|
||||||
|
// style of column H on Sheet1:
|
||||||
|
//
|
||||||
|
// err := sw.SetColStyle(8, 8, style)
|
||||||
|
func (sw *StreamWriter) SetColStyle(minVal, maxVal, styleID int) error {
|
||||||
|
if sw.sheetWritten {
|
||||||
|
return ErrStreamSetColStyle
|
||||||
|
}
|
||||||
|
if minVal < MinColumns || minVal > MaxColumns || maxVal < MinColumns || maxVal > MaxColumns {
|
||||||
|
return ErrColumnNumber
|
||||||
|
}
|
||||||
|
if maxVal < minVal {
|
||||||
|
minVal, maxVal = maxVal, minVal
|
||||||
|
}
|
||||||
|
s, err := sw.file.stylesReader()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if styleID < 0 || s.CellXfs == nil || len(s.CellXfs.Xf) <= styleID {
|
||||||
|
return newInvalidStyleID(styleID)
|
||||||
|
}
|
||||||
|
sw.worksheet.setColStyle(minVal, maxVal, styleID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetColWidth provides a function to set the width of a single column or
|
// SetColWidth provides a function to set the width of a single column or
|
||||||
// multiple columns for the StreamWriter. Note that you must call
|
// multiple columns for the StreamWriter. Note that you must call
|
||||||
// the 'SetColWidth' function before the 'SetRow' function. For example set
|
// the 'SetColWidth' function before the 'SetRow' function. For example set
|
||||||
|
@ -452,14 +480,7 @@ func (sw *StreamWriter) SetColWidth(minVal, maxVal int, width float64) error {
|
||||||
if minVal > maxVal {
|
if minVal > maxVal {
|
||||||
minVal, maxVal = maxVal, minVal
|
minVal, maxVal = maxVal, minVal
|
||||||
}
|
}
|
||||||
|
sw.worksheet.setColWidth(minVal, maxVal, width)
|
||||||
sw.cols.WriteString(`<col min="`)
|
|
||||||
sw.cols.WriteString(strconv.Itoa(minVal))
|
|
||||||
sw.cols.WriteString(`" max="`)
|
|
||||||
sw.cols.WriteString(strconv.Itoa(maxVal))
|
|
||||||
sw.cols.WriteString(`" width="`)
|
|
||||||
sw.cols.WriteString(strconv.FormatFloat(width, 'f', -1, 64))
|
|
||||||
sw.cols.WriteString(`" customWidth="1"/>`)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,15 +578,15 @@ func (sw *StreamWriter) setCellValFunc(c *xlsxC, val interface{}) error {
|
||||||
func setCellIntFunc(c *xlsxC, val interface{}) {
|
func setCellIntFunc(c *xlsxC, val interface{}) {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case int:
|
case int:
|
||||||
c.T, c.V = setCellInt(val)
|
c.T, c.V = setCellInt(int64(val))
|
||||||
case int8:
|
case int8:
|
||||||
c.T, c.V = setCellInt(int(val))
|
c.T, c.V = setCellInt(int64(val))
|
||||||
case int16:
|
case int16:
|
||||||
c.T, c.V = setCellInt(int(val))
|
c.T, c.V = setCellInt(int64(val))
|
||||||
case int32:
|
case int32:
|
||||||
c.T, c.V = setCellInt(int(val))
|
c.T, c.V = setCellInt(int64(val))
|
||||||
case int64:
|
case int64:
|
||||||
c.T, c.V = setCellInt(int(val))
|
c.T, c.V = setCellInt(val)
|
||||||
case uint:
|
case uint:
|
||||||
c.T, c.V = setCellUint(uint64(val))
|
c.T, c.V = setCellUint(uint64(val))
|
||||||
case uint8:
|
case uint8:
|
||||||
|
@ -642,9 +663,26 @@ func writeCell(buf *bufferedWriter, c xlsxC) {
|
||||||
func (sw *StreamWriter) writeSheetData() {
|
func (sw *StreamWriter) writeSheetData() {
|
||||||
if !sw.sheetWritten {
|
if !sw.sheetWritten {
|
||||||
bulkAppendFields(&sw.rawData, sw.worksheet, 4, 5)
|
bulkAppendFields(&sw.rawData, sw.worksheet, 4, 5)
|
||||||
if sw.cols.Len() > 0 {
|
if sw.worksheet.Cols != nil {
|
||||||
_, _ = sw.rawData.WriteString("<cols>")
|
_, _ = sw.rawData.WriteString("<cols>")
|
||||||
_, _ = sw.rawData.WriteString(sw.cols.String())
|
for _, col := range sw.worksheet.Cols.Col {
|
||||||
|
sw.rawData.WriteString(`<col min="`)
|
||||||
|
sw.rawData.WriteString(strconv.Itoa(col.Min))
|
||||||
|
sw.rawData.WriteString(`" max="`)
|
||||||
|
sw.rawData.WriteString(strconv.Itoa(col.Max))
|
||||||
|
sw.rawData.WriteString(`"`)
|
||||||
|
if col.Width != nil {
|
||||||
|
sw.rawData.WriteString(` width="`)
|
||||||
|
sw.rawData.WriteString(strconv.FormatFloat(*col.Width, 'f', -1, 64))
|
||||||
|
sw.rawData.WriteString(`" customWidth="1"`)
|
||||||
|
}
|
||||||
|
if col.Style != 0 {
|
||||||
|
sw.rawData.WriteString(` style="`)
|
||||||
|
sw.rawData.WriteString(strconv.Itoa(col.Style))
|
||||||
|
sw.rawData.WriteString(`"`)
|
||||||
|
}
|
||||||
|
sw.rawData.WriteString(`/>`)
|
||||||
|
}
|
||||||
_, _ = sw.rawData.WriteString("</cols>")
|
_, _ = sw.rawData.WriteString("</cols>")
|
||||||
}
|
}
|
||||||
_, _ = sw.rawData.WriteString(`<sheetData>`)
|
_, _ = sw.rawData.WriteString(`<sheetData>`)
|
||||||
|
|
|
@ -154,19 +154,53 @@ func TestStreamWriter(t *testing.T) {
|
||||||
assert.NoError(t, file.Close())
|
assert.NoError(t, file.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStreamSetColWidth(t *testing.T) {
|
func TestStreamSetColStyle(t *testing.T) {
|
||||||
file := NewFile()
|
file := NewFile()
|
||||||
defer func() {
|
defer func() {
|
||||||
assert.NoError(t, file.Close())
|
assert.NoError(t, file.Close())
|
||||||
}()
|
}()
|
||||||
streamWriter, err := file.NewStreamWriter("Sheet1")
|
streamWriter, err := file.NewStreamWriter("Sheet1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, streamWriter.SetColStyle(3, 2, 0))
|
||||||
|
assert.Equal(t, ErrColumnNumber, streamWriter.SetColStyle(0, 3, 20))
|
||||||
|
assert.Equal(t, ErrColumnNumber, streamWriter.SetColStyle(MaxColumns+1, 3, 20))
|
||||||
|
assert.Equal(t, newInvalidStyleID(2), streamWriter.SetColStyle(1, 3, 2))
|
||||||
|
assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"}))
|
||||||
|
assert.Equal(t, ErrStreamSetColStyle, streamWriter.SetColStyle(2, 3, 0))
|
||||||
|
|
||||||
|
file = NewFile()
|
||||||
|
defer func() {
|
||||||
|
assert.NoError(t, file.Close())
|
||||||
|
}()
|
||||||
|
// Test set column style with unsupported charset style sheet
|
||||||
|
file.Styles = nil
|
||||||
|
file.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
|
||||||
|
streamWriter, err = file.NewStreamWriter("Sheet1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualError(t, streamWriter.SetColStyle(3, 2, 0), "XML syntax error on line 1: invalid UTF-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamSetColWidth(t *testing.T) {
|
||||||
|
file := NewFile()
|
||||||
|
defer func() {
|
||||||
|
assert.NoError(t, file.Close())
|
||||||
|
}()
|
||||||
|
styleID, err := file.NewStyle(&Style{
|
||||||
|
Fill: Fill{Type: "pattern", Color: []string{"E0EBF5"}, Pattern: 1},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
streamWriter, err := file.NewStreamWriter("Sheet1")
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, streamWriter.SetColWidth(3, 2, 20))
|
assert.NoError(t, streamWriter.SetColWidth(3, 2, 20))
|
||||||
|
assert.NoError(t, streamWriter.SetColStyle(3, 2, styleID))
|
||||||
assert.Equal(t, ErrColumnNumber, streamWriter.SetColWidth(0, 3, 20))
|
assert.Equal(t, ErrColumnNumber, streamWriter.SetColWidth(0, 3, 20))
|
||||||
assert.Equal(t, ErrColumnNumber, streamWriter.SetColWidth(MaxColumns+1, 3, 20))
|
assert.Equal(t, ErrColumnNumber, streamWriter.SetColWidth(MaxColumns+1, 3, 20))
|
||||||
assert.Equal(t, ErrColumnWidth, streamWriter.SetColWidth(1, 3, MaxColumnWidth+1))
|
assert.Equal(t, ErrColumnWidth, streamWriter.SetColWidth(1, 3, MaxColumnWidth+1))
|
||||||
assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"}))
|
assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"}))
|
||||||
assert.Equal(t, ErrStreamSetColWidth, streamWriter.SetColWidth(2, 3, 20))
|
assert.Equal(t, ErrStreamSetColWidth, streamWriter.SetColWidth(2, 3, 20))
|
||||||
|
assert.NoError(t, streamWriter.Flush())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStreamSetPanes(t *testing.T) {
|
func TestStreamSetPanes(t *testing.T) {
|
||||||
|
@ -323,7 +357,6 @@ func TestStreamSetRowWithStyle(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
assert.NoError(t, file.Close())
|
assert.NoError(t, file.Close())
|
||||||
}()
|
}()
|
||||||
zeroStyleID := 0
|
|
||||||
grayStyleID, err := file.NewStyle(&Style{Font: &Font{Color: "777777"}})
|
grayStyleID, err := file.NewStyle(&Style{Font: &Font{Color: "777777"}})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
blueStyleID, err := file.NewStyle(&Style{Font: &Font{Color: "0000FF"}})
|
blueStyleID, err := file.NewStyle(&Style{Font: &Font{Color: "0000FF"}})
|
||||||
|
@ -342,7 +375,7 @@ func TestStreamSetRowWithStyle(t *testing.T) {
|
||||||
|
|
||||||
ws, err := file.workSheetReader("Sheet1")
|
ws, err := file.workSheetReader("Sheet1")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
for colIdx, expected := range []int{grayStyleID, zeroStyleID, zeroStyleID, blueStyleID, blueStyleID} {
|
for colIdx, expected := range []int{grayStyleID, grayStyleID, grayStyleID, blueStyleID, blueStyleID} {
|
||||||
assert.Equal(t, expected, ws.SheetData.Row[0].C[colIdx].S)
|
assert.Equal(t, expected, ws.SheetData.Row[0].C[colIdx].S)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
40
styles.go
40
styles.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -1441,8 +1441,8 @@ func (f *File) getThemeColor(clr *xlsxColor) string {
|
||||||
func (f *File) extractBorders(bdr *xlsxBorder, s *xlsxStyleSheet, style *Style) {
|
func (f *File) extractBorders(bdr *xlsxBorder, s *xlsxStyleSheet, style *Style) {
|
||||||
if bdr != nil {
|
if bdr != nil {
|
||||||
var borders []Border
|
var borders []Border
|
||||||
extractBorder := func(lineType string, line xlsxLine) {
|
extractBorder := func(lineType string, line *xlsxLine) {
|
||||||
if line.Style != "" {
|
if line != nil && line.Style != "" {
|
||||||
borders = append(borders, Border{
|
borders = append(borders, Border{
|
||||||
Type: lineType,
|
Type: lineType,
|
||||||
Color: f.getThemeColor(line.Color),
|
Color: f.getThemeColor(line.Color),
|
||||||
|
@ -1450,7 +1450,7 @@ func (f *File) extractBorders(bdr *xlsxBorder, s *xlsxStyleSheet, style *Style)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, line := range []xlsxLine{
|
for i, line := range []*xlsxLine{
|
||||||
bdr.Left, bdr.Right, bdr.Top, bdr.Bottom, bdr.Diagonal, bdr.Diagonal,
|
bdr.Left, bdr.Right, bdr.Top, bdr.Bottom, bdr.Diagonal, bdr.Diagonal,
|
||||||
} {
|
} {
|
||||||
if i < 4 {
|
if i < 4 {
|
||||||
|
@ -2051,11 +2051,12 @@ func newFills(style *Style, fg bool) *xlsxFill {
|
||||||
if style.Fill.Pattern > 18 || style.Fill.Pattern < 0 {
|
if style.Fill.Pattern > 18 || style.Fill.Pattern < 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if len(style.Fill.Color) < 1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
var pattern xlsxPatternFill
|
var pattern xlsxPatternFill
|
||||||
pattern.PatternType = styleFillPatterns[style.Fill.Pattern]
|
pattern.PatternType = styleFillPatterns[style.Fill.Pattern]
|
||||||
|
if len(style.Fill.Color) < 1 {
|
||||||
|
fill.PatternFill = &pattern
|
||||||
|
break
|
||||||
|
}
|
||||||
if fg {
|
if fg {
|
||||||
if pattern.FgColor == nil {
|
if pattern.FgColor == nil {
|
||||||
pattern.FgColor = new(xlsxColor)
|
pattern.FgColor = new(xlsxColor)
|
||||||
|
@ -2127,29 +2128,20 @@ func newBorders(style *Style) *xlsxBorder {
|
||||||
var border xlsxBorder
|
var border xlsxBorder
|
||||||
for _, v := range style.Border {
|
for _, v := range style.Border {
|
||||||
if 0 <= v.Style && v.Style < 14 {
|
if 0 <= v.Style && v.Style < 14 {
|
||||||
var color xlsxColor
|
line := &xlsxLine{Style: styleBorders[v.Style], Color: &xlsxColor{RGB: getPaletteColor(v.Color)}}
|
||||||
color.RGB = getPaletteColor(v.Color)
|
|
||||||
switch v.Type {
|
switch v.Type {
|
||||||
case "left":
|
case "left":
|
||||||
border.Left.Style = styleBorders[v.Style]
|
border.Left = line
|
||||||
border.Left.Color = &color
|
|
||||||
case "right":
|
case "right":
|
||||||
border.Right.Style = styleBorders[v.Style]
|
border.Right = line
|
||||||
border.Right.Color = &color
|
|
||||||
case "top":
|
case "top":
|
||||||
border.Top.Style = styleBorders[v.Style]
|
border.Top = line
|
||||||
border.Top.Color = &color
|
|
||||||
case "bottom":
|
case "bottom":
|
||||||
border.Bottom.Style = styleBorders[v.Style]
|
border.Bottom = line
|
||||||
border.Bottom.Color = &color
|
|
||||||
case "diagonalUp":
|
case "diagonalUp":
|
||||||
border.Diagonal.Style = styleBorders[v.Style]
|
border.Diagonal, border.DiagonalUp = line, true
|
||||||
border.Diagonal.Color = &color
|
|
||||||
border.DiagonalUp = true
|
|
||||||
case "diagonalDown":
|
case "diagonalDown":
|
||||||
border.Diagonal.Style = styleBorders[v.Style]
|
border.Diagonal, border.DiagonalDown = line, true
|
||||||
border.Diagonal.Color = &color
|
|
||||||
border.DiagonalDown = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
table.go
4
table.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
14
templates.go
14
templates.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
//
|
//
|
||||||
// This file contains default templates for XML files we don't yet populated
|
// This file contains default templates for XML files we don't yet populated
|
||||||
// based on content.
|
// based on content.
|
||||||
|
@ -495,9 +495,19 @@ var supportedDrawingUnderlineTypes = []string{
|
||||||
"wavyDbl",
|
"wavyDbl",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// supportedDrawingTextVerticalType defined supported text vertical types in
|
||||||
|
// drawing markup language.
|
||||||
|
var supportedDrawingTextVerticalType = []string{"horz", "vert", "vert270", "wordArtVert", "eaVert", "mongolianVert", "wordArtVertRtl"}
|
||||||
|
|
||||||
// supportedPositioning defined supported positioning types.
|
// supportedPositioning defined supported positioning types.
|
||||||
var supportedPositioning = []string{"absolute", "oneCell", "twoCell"}
|
var supportedPositioning = []string{"absolute", "oneCell", "twoCell"}
|
||||||
|
|
||||||
|
// supportedPageOrientation defined supported page setup page orientation.
|
||||||
|
var supportedPageOrientation = []string{"portrait", "landscape"}
|
||||||
|
|
||||||
|
// supportedPageOrder defined supported page setup page order.
|
||||||
|
var supportedPageOrder = []string{"overThenDown", "downThenOver"}
|
||||||
|
|
||||||
// builtInDefinedNames defined built-in defined names are built with a _xlnm prefix.
|
// builtInDefinedNames defined built-in defined names are built with a _xlnm prefix.
|
||||||
var builtInDefinedNames = []string{"_xlnm.Print_Area", "_xlnm.Print_Titles", "_xlnm.Criteria", "_xlnm._FilterDatabase", "_xlnm.Extract", "_xlnm.Consolidate_Area", "_xlnm.Database", "_xlnm.Sheet_Title"}
|
var builtInDefinedNames = []string{"_xlnm.Print_Area", "_xlnm.Print_Titles", "_xlnm.Criteria", "_xlnm._FilterDatabase", "_xlnm.Extract", "_xlnm.Consolidate_Area", "_xlnm.Database", "_xlnm.Sheet_Title"}
|
||||||
|
|
||||||
|
|
158
vml.go
158
vml.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -36,6 +36,16 @@ const (
|
||||||
FormControlScrollBar
|
FormControlScrollBar
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HeaderFooterImagePositionType is the type of header and footer image position.
|
||||||
|
type HeaderFooterImagePositionType byte
|
||||||
|
|
||||||
|
// Worksheet header and footer image position types enumeration.
|
||||||
|
const (
|
||||||
|
HeaderFooterImagePositionLeft HeaderFooterImagePositionType = iota
|
||||||
|
HeaderFooterImagePositionCenter
|
||||||
|
HeaderFooterImagePositionRight
|
||||||
|
)
|
||||||
|
|
||||||
// GetComments retrieves all comments in a worksheet by given worksheet name.
|
// GetComments retrieves all comments in a worksheet by given worksheet name.
|
||||||
func (f *File) GetComments(sheet string) ([]Comment, error) {
|
func (f *File) GetComments(sheet string) ([]Comment, error) {
|
||||||
var comments []Comment
|
var comments []Comment
|
||||||
|
@ -519,6 +529,7 @@ func (f *File) addVMLObject(opts vmlOptions) error {
|
||||||
}
|
}
|
||||||
vmlID = f.countVMLDrawing() + 1
|
vmlID = f.countVMLDrawing() + 1
|
||||||
}
|
}
|
||||||
|
sheetID := f.getSheetID(opts.sheet)
|
||||||
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||||
sheetRelationshipsDrawingVML := "../drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
sheetRelationshipsDrawingVML := "../drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||||
sheetXMLPath, _ := f.getSheetXMLPath(opts.sheet)
|
sheetXMLPath, _ := f.getSheetXMLPath(opts.sheet)
|
||||||
|
@ -534,7 +545,7 @@ func (f *File) addVMLObject(opts vmlOptions) error {
|
||||||
f.addSheetNameSpace(opts.sheet, SourceRelationship)
|
f.addSheetNameSpace(opts.sheet, SourceRelationship)
|
||||||
f.addSheetLegacyDrawing(opts.sheet, rID)
|
f.addSheetLegacyDrawing(opts.sheet, rID)
|
||||||
}
|
}
|
||||||
if err = f.addDrawingVML(vmlID, drawingVML, prepareFormCtrlOptions(&opts)); err != nil {
|
if err = f.addDrawingVML(sheetID, drawingVML, prepareFormCtrlOptions(&opts)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !opts.formCtrl {
|
if !opts.formCtrl {
|
||||||
|
@ -823,7 +834,7 @@ func (f *File) addFormCtrlShape(preset formCtrlPreset, col, row int, anchor stri
|
||||||
// anchor value is a comma-separated list of data written out as: LeftColumn,
|
// anchor value is a comma-separated list of data written out as: LeftColumn,
|
||||||
// LeftOffset, TopRow, TopOffset, RightColumn, RightOffset, BottomRow,
|
// LeftOffset, TopRow, TopOffset, RightColumn, RightOffset, BottomRow,
|
||||||
// BottomOffset.
|
// BottomOffset.
|
||||||
func (f *File) addDrawingVML(dataID int, drawingVML string, opts *vmlOptions) error {
|
func (f *File) addDrawingVML(sheetID int, drawingVML string, opts *vmlOptions) error {
|
||||||
col, row, err := CellNameToCoordinates(opts.FormControl.Cell)
|
col, row, err := CellNameToCoordinates(opts.FormControl.Cell)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -843,7 +854,7 @@ func (f *File) addDrawingVML(dataID int, drawingVML string, opts *vmlOptions) er
|
||||||
XMLNSx: "urn:schemas-microsoft-com:office:excel",
|
XMLNSx: "urn:schemas-microsoft-com:office:excel",
|
||||||
XMLNSmv: "http://macVmlSchemaUri",
|
XMLNSmv: "http://macVmlSchemaUri",
|
||||||
ShapeLayout: &xlsxShapeLayout{
|
ShapeLayout: &xlsxShapeLayout{
|
||||||
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: dataID},
|
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: sheetID},
|
||||||
},
|
},
|
||||||
ShapeType: &xlsxShapeType{
|
ShapeType: &xlsxShapeType{
|
||||||
ID: fmt.Sprintf("_x0000_t%d", vmlID),
|
ID: fmt.Sprintf("_x0000_t%d", vmlID),
|
||||||
|
@ -1070,3 +1081,140 @@ func extractVMLFont(font []decodeVMLFont) []RichTextRun {
|
||||||
}
|
}
|
||||||
return runs
|
return runs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddHeaderFooterImage provides a mechanism to set the graphics that can be
|
||||||
|
// referenced in the header and footer definitions via &G, supported image
|
||||||
|
// types: EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ.
|
||||||
|
//
|
||||||
|
// The extension should be provided with a "." in front, e.g. ".png".
|
||||||
|
// The width and height should have units in them, e.g. "100pt".
|
||||||
|
func (f *File) AddHeaderFooterImage(sheet string, opts *HeaderFooterImageOptions) error {
|
||||||
|
ws, err := f.workSheetReader(sheet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ext, ok := supportedImageTypes[strings.ToLower(opts.Extension)]
|
||||||
|
if !ok {
|
||||||
|
return ErrImgExt
|
||||||
|
}
|
||||||
|
sheetID := f.getSheetID(sheet)
|
||||||
|
vmlID := f.countVMLDrawing() + 1
|
||||||
|
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||||
|
sheetRelationshipsDrawingVML := "../drawings/vmlDrawing" + strconv.Itoa(vmlID) + ".vml"
|
||||||
|
sheetXMLPath, _ := f.getSheetXMLPath(sheet)
|
||||||
|
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetXMLPath, "xl/worksheets/") + ".rels"
|
||||||
|
if ws.LegacyDrawingHF != nil {
|
||||||
|
// The worksheet already has a VML relationships, use the relationships drawing ../drawings/vmlDrawing%d.vml.
|
||||||
|
sheetRelationshipsDrawingVML = f.getSheetRelationshipsTargetByID(sheet, ws.LegacyDrawingHF.RID)
|
||||||
|
vmlID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingVML, "../drawings/vmlDrawing"), ".vml"))
|
||||||
|
drawingVML = strings.ReplaceAll(sheetRelationshipsDrawingVML, "..", "xl")
|
||||||
|
} else {
|
||||||
|
// Add first VML drawing for given sheet.
|
||||||
|
rID := f.addRels(sheetRels, SourceRelationshipDrawingVML, sheetRelationshipsDrawingVML, "")
|
||||||
|
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||||
|
f.addSheetLegacyDrawingHF(sheet, rID)
|
||||||
|
}
|
||||||
|
|
||||||
|
shapeID := map[HeaderFooterImagePositionType]string{
|
||||||
|
HeaderFooterImagePositionLeft: "L",
|
||||||
|
HeaderFooterImagePositionCenter: "C",
|
||||||
|
HeaderFooterImagePositionRight: "R",
|
||||||
|
}[opts.Position] +
|
||||||
|
map[bool]string{false: "H", true: "F"}[opts.IsFooter] +
|
||||||
|
map[bool]string{false: "", true: "FIRST"}[opts.FirstPage]
|
||||||
|
vml := f.VMLDrawing[drawingVML]
|
||||||
|
if vml == nil {
|
||||||
|
vml = &vmlDrawing{
|
||||||
|
XMLNSv: "urn:schemas-microsoft-com:vml",
|
||||||
|
XMLNSo: "urn:schemas-microsoft-com:office:office",
|
||||||
|
XMLNSx: "urn:schemas-microsoft-com:office:excel",
|
||||||
|
ShapeLayout: &xlsxShapeLayout{
|
||||||
|
Ext: "edit", IDmap: &xlsxIDmap{Ext: "edit", Data: sheetID},
|
||||||
|
},
|
||||||
|
ShapeType: &xlsxShapeType{
|
||||||
|
ID: "_x0000_t75",
|
||||||
|
CoordSize: "21600,21600",
|
||||||
|
Spt: 75,
|
||||||
|
PreferRelative: "t",
|
||||||
|
Path: "m@4@5l@4@11@9@11@9@5xe",
|
||||||
|
Filled: "f",
|
||||||
|
Stroked: "f",
|
||||||
|
Stroke: &xlsxStroke{JoinStyle: "miter"},
|
||||||
|
VFormulas: &vFormulas{
|
||||||
|
Formulas: []vFormula{
|
||||||
|
{Equation: "if lineDrawn pixelLineWidth 0"},
|
||||||
|
{Equation: "sum @0 1 0"},
|
||||||
|
{Equation: "sum 0 0 @1"},
|
||||||
|
{Equation: "prod @2 1 2"},
|
||||||
|
{Equation: "prod @3 21600 pixelWidth"},
|
||||||
|
{Equation: "prod @3 21600 pixelHeight"},
|
||||||
|
{Equation: "sum @0 0 1"},
|
||||||
|
{Equation: "prod @6 1 2"},
|
||||||
|
{Equation: "prod @7 21600 pixelWidth"},
|
||||||
|
{Equation: "sum @8 21600 0"},
|
||||||
|
{Equation: "prod @7 21600 pixelHeight"},
|
||||||
|
{Equation: "sum @10 21600 0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VPath: &vPath{ExtrusionOK: "f", GradientShapeOK: "t", ConnectType: "rect"},
|
||||||
|
Lock: &oLock{Ext: "edit", AspectRatio: "t"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// Load exist VML shapes from xl/drawings/vmlDrawing%d.vml
|
||||||
|
d, err := f.decodeVMLDrawingReader(drawingVML)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if d != nil {
|
||||||
|
vml.ShapeType.ID = d.ShapeType.ID
|
||||||
|
vml.ShapeType.CoordSize = d.ShapeType.CoordSize
|
||||||
|
vml.ShapeType.Spt = d.ShapeType.Spt
|
||||||
|
vml.ShapeType.PreferRelative = d.ShapeType.PreferRelative
|
||||||
|
vml.ShapeType.Path = d.ShapeType.Path
|
||||||
|
vml.ShapeType.Filled = d.ShapeType.Filled
|
||||||
|
vml.ShapeType.Stroked = d.ShapeType.Stroked
|
||||||
|
for _, v := range d.Shape {
|
||||||
|
s := xlsxShape{
|
||||||
|
ID: v.ID,
|
||||||
|
SpID: v.SpID,
|
||||||
|
Type: v.Type,
|
||||||
|
Style: v.Style,
|
||||||
|
Val: v.Val,
|
||||||
|
}
|
||||||
|
vml.Shape = append(vml.Shape, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, shape := range vml.Shape {
|
||||||
|
if shape.ID == shapeID {
|
||||||
|
vml.Shape = append(vml.Shape[:idx], vml.Shape[idx+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
style := fmt.Sprintf("position:absolute;margin-left:0;margin-top:0;width:%s;height:%s;z-index:1", opts.Width, opts.Height)
|
||||||
|
drawingVMLRels := "xl/drawings/_rels/vmlDrawing" + strconv.Itoa(vmlID) + ".vml.rels"
|
||||||
|
|
||||||
|
mediaStr := ".." + strings.TrimPrefix(f.addMedia(opts.File, ext), "xl")
|
||||||
|
imageID := f.addRels(drawingVMLRels, SourceRelationshipImage, mediaStr, "")
|
||||||
|
|
||||||
|
shape := xlsxShape{
|
||||||
|
ID: shapeID,
|
||||||
|
SpID: "_x0000_s1025",
|
||||||
|
Type: "#_x0000_t75",
|
||||||
|
Style: style,
|
||||||
|
}
|
||||||
|
sp, _ := xml.Marshal(encodeShape{
|
||||||
|
ImageData: &vImageData{RelID: "rId" + strconv.Itoa(imageID)},
|
||||||
|
Lock: &oLock{Ext: "edit", Rotation: "t"},
|
||||||
|
})
|
||||||
|
|
||||||
|
shape.Val = string(sp[13 : len(sp)-14])
|
||||||
|
vml.Shape = append(vml.Shape, shape)
|
||||||
|
f.VMLDrawing[drawingVML] = vml
|
||||||
|
|
||||||
|
if err := f.setContentTypePartImageExtensions(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f.setContentTypePartVMLExtensions()
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ type vmlDrawing struct {
|
||||||
XMLNSv string `xml:"xmlns:v,attr"`
|
XMLNSv string `xml:"xmlns:v,attr"`
|
||||||
XMLNSo string `xml:"xmlns:o,attr"`
|
XMLNSo string `xml:"xmlns:o,attr"`
|
||||||
XMLNSx string `xml:"xmlns:x,attr"`
|
XMLNSx string `xml:"xmlns:x,attr"`
|
||||||
XMLNSmv string `xml:"xmlns:mv,attr"`
|
XMLNSmv string `xml:"xmlns:mv,attr,omitempty"`
|
||||||
ShapeLayout *xlsxShapeLayout `xml:"o:shapelayout"`
|
ShapeLayout *xlsxShapeLayout `xml:"o:shapelayout"`
|
||||||
ShapeType *xlsxShapeType `xml:"v:shapetype"`
|
ShapeType *xlsxShapeType `xml:"v:shapetype"`
|
||||||
Shape []xlsxShape `xml:"v:shape"`
|
Shape []xlsxShape `xml:"v:shape"`
|
||||||
|
@ -44,6 +44,7 @@ type xlsxIDmap struct {
|
||||||
type xlsxShape struct {
|
type xlsxShape struct {
|
||||||
XMLName xml.Name `xml:"v:shape"`
|
XMLName xml.Name `xml:"v:shape"`
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
|
SpID string `xml:"o:spid,attr,omitempty"`
|
||||||
Type string `xml:"type,attr"`
|
Type string `xml:"type,attr"`
|
||||||
Style string `xml:"style,attr"`
|
Style string `xml:"style,attr"`
|
||||||
Button string `xml:"o:button,attr,omitempty"`
|
Button string `xml:"o:button,attr,omitempty"`
|
||||||
|
@ -60,9 +61,14 @@ type xlsxShapeType struct {
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
CoordSize string `xml:"coordsize,attr"`
|
CoordSize string `xml:"coordsize,attr"`
|
||||||
Spt int `xml:"o:spt,attr"`
|
Spt int `xml:"o:spt,attr"`
|
||||||
|
PreferRelative string `xml:"o:preferrelative,attr,omitempty"`
|
||||||
Path string `xml:"path,attr"`
|
Path string `xml:"path,attr"`
|
||||||
|
Filled string `xml:"filled,attr,omitempty"`
|
||||||
|
Stroked string `xml:"stroked,attr,omitempty"`
|
||||||
Stroke *xlsxStroke `xml:"v:stroke"`
|
Stroke *xlsxStroke `xml:"v:stroke"`
|
||||||
|
VFormulas *vFormulas `xml:"v:formulas"`
|
||||||
VPath *vPath `xml:"v:path"`
|
VPath *vPath `xml:"v:path"`
|
||||||
|
Lock *oLock `xml:"o:lock"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxStroke directly maps the stroke element.
|
// xlsxStroke directly maps the stroke element.
|
||||||
|
@ -72,10 +78,28 @@ type xlsxStroke struct {
|
||||||
|
|
||||||
// vPath directly maps the v:path element.
|
// vPath directly maps the v:path element.
|
||||||
type vPath struct {
|
type vPath struct {
|
||||||
|
ExtrusionOK string `xml:"o:extrusionok,attr,omitempty"`
|
||||||
GradientShapeOK string `xml:"gradientshapeok,attr,omitempty"`
|
GradientShapeOK string `xml:"gradientshapeok,attr,omitempty"`
|
||||||
ConnectType string `xml:"o:connecttype,attr"`
|
ConnectType string `xml:"o:connecttype,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// oLock directly maps the o:lock element.
|
||||||
|
type oLock struct {
|
||||||
|
Ext string `xml:"v:ext,attr"`
|
||||||
|
Rotation string `xml:"rotation,attr,omitempty"`
|
||||||
|
AspectRatio string `xml:"aspectratio,attr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// vFormulas directly maps to the v:formulas element
|
||||||
|
type vFormulas struct {
|
||||||
|
Formulas []vFormula `xml:"v:f"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// vFormula directly maps to the v:f element
|
||||||
|
type vFormula struct {
|
||||||
|
Equation string `xml:"eqn,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
// vFill directly maps the v:fill element. This element must be defined within a
|
// vFill directly maps the v:fill element. This element must be defined within a
|
||||||
// Shape element.
|
// Shape element.
|
||||||
type vFill struct {
|
type vFill struct {
|
||||||
|
@ -106,6 +130,13 @@ type vTextBox struct {
|
||||||
Div *xlsxDiv `xml:"div"`
|
Div *xlsxDiv `xml:"div"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vImageData directly maps the v:imagedata element. This element must be
|
||||||
|
// defined within a Shape element.
|
||||||
|
type vImageData struct {
|
||||||
|
RelID string `xml:"o:relid,attr"`
|
||||||
|
Title string `xml:"o:title,attr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// xlsxDiv directly maps the div element.
|
// xlsxDiv directly maps the div element.
|
||||||
type xlsxDiv struct {
|
type xlsxDiv struct {
|
||||||
Style string `xml:"style,attr"`
|
Style string `xml:"style,attr"`
|
||||||
|
@ -165,12 +196,16 @@ type decodeShapeType struct {
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
CoordSize string `xml:"coordsize,attr"`
|
CoordSize string `xml:"coordsize,attr"`
|
||||||
Spt int `xml:"spt,attr"`
|
Spt int `xml:"spt,attr"`
|
||||||
|
PreferRelative string `xml:"preferrelative,attr,omitempty"`
|
||||||
Path string `xml:"path,attr"`
|
Path string `xml:"path,attr"`
|
||||||
|
Filled string `xml:"filled,attr,omitempty"`
|
||||||
|
Stroked string `xml:"stroked,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeShape defines the structure used to parse the particular shape element.
|
// decodeShape defines the structure used to parse the particular shape element.
|
||||||
type decodeShape struct {
|
type decodeShape struct {
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
|
SpID string `xml:"spid,attr,omitempty"`
|
||||||
Type string `xml:"type,attr"`
|
Type string `xml:"type,attr"`
|
||||||
Style string `xml:"style,attr"`
|
Style string `xml:"style,attr"`
|
||||||
Button string `xml:"button,attr,omitempty"`
|
Button string `xml:"button,attr,omitempty"`
|
||||||
|
@ -254,7 +289,9 @@ type encodeShape struct {
|
||||||
Shadow *vShadow `xml:"v:shadow"`
|
Shadow *vShadow `xml:"v:shadow"`
|
||||||
Path *vPath `xml:"v:path"`
|
Path *vPath `xml:"v:path"`
|
||||||
TextBox *vTextBox `xml:"v:textbox"`
|
TextBox *vTextBox `xml:"v:textbox"`
|
||||||
|
ImageData *vImageData `xml:"v:imagedata"`
|
||||||
ClientData *xClientData `xml:"x:ClientData"`
|
ClientData *xClientData `xml:"x:ClientData"`
|
||||||
|
Lock *oLock `xml:"o:lock"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// formCtrlPreset defines the structure used to form control presets.
|
// formCtrlPreset defines the structure used to form control presets.
|
||||||
|
@ -301,3 +338,15 @@ type FormControl struct {
|
||||||
Type FormControlType
|
Type FormControlType
|
||||||
Format GraphicOptions
|
Format GraphicOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HeaderFooterImageOptions defines the settings for an image to be accessible
|
||||||
|
// from the worksheet header and footer options.
|
||||||
|
type HeaderFooterImageOptions struct {
|
||||||
|
Position HeaderFooterImagePositionType
|
||||||
|
File []byte
|
||||||
|
IsFooter bool
|
||||||
|
FirstPage bool
|
||||||
|
Extension string
|
||||||
|
Width string
|
||||||
|
Height string
|
||||||
|
}
|
||||||
|
|
101
vml_test.go
101
vml_test.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -412,3 +412,100 @@ func TestExtractFormControl(t *testing.T) {
|
||||||
_, err := extractFormControl(string(MacintoshCyrillicCharset))
|
_, err := extractFormControl(string(MacintoshCyrillicCharset))
|
||||||
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddHeaderFooterImage(t *testing.T) {
|
||||||
|
f, sheet, wb := NewFile(), "Sheet1", filepath.Join("test", "TestAddHeaderFooterImage.xlsx")
|
||||||
|
headerFooterOptions := HeaderFooterOptions{
|
||||||
|
DifferentFirst: true,
|
||||||
|
OddHeader: "&L&GExcelize&C&G&R&G",
|
||||||
|
OddFooter: "&L&GExcelize&C&G&R&G",
|
||||||
|
FirstHeader: "&L&GExcelize&C&G&R&G",
|
||||||
|
FirstFooter: "&L&GExcelize&C&G&R&G",
|
||||||
|
}
|
||||||
|
assert.NoError(t, f.SetHeaderFooter(sheet, &headerFooterOptions))
|
||||||
|
assert.NoError(t, f.SetSheetView(sheet, -1, &ViewOptions{View: stringPtr("pageLayout")}))
|
||||||
|
images := map[string][]byte{
|
||||||
|
".wmf": nil, ".tif": nil, ".png": nil,
|
||||||
|
".jpg": nil, ".gif": nil, ".emz": nil, ".emf": nil,
|
||||||
|
}
|
||||||
|
for ext := range images {
|
||||||
|
img, err := os.ReadFile(filepath.Join("test", "images", "excel"+ext))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
images[ext] = img
|
||||||
|
}
|
||||||
|
for _, opt := range []struct {
|
||||||
|
position HeaderFooterImagePositionType
|
||||||
|
file []byte
|
||||||
|
isFooter bool
|
||||||
|
firstPage bool
|
||||||
|
ext string
|
||||||
|
}{
|
||||||
|
{position: HeaderFooterImagePositionLeft, file: images[".tif"], firstPage: true, ext: ".tif"},
|
||||||
|
{position: HeaderFooterImagePositionCenter, file: images[".gif"], firstPage: true, ext: ".gif"},
|
||||||
|
{position: HeaderFooterImagePositionRight, file: images[".png"], firstPage: true, ext: ".png"},
|
||||||
|
{position: HeaderFooterImagePositionLeft, file: images[".emf"], isFooter: true, firstPage: true, ext: ".emf"},
|
||||||
|
{position: HeaderFooterImagePositionCenter, file: images[".wmf"], isFooter: true, firstPage: true, ext: ".wmf"},
|
||||||
|
{position: HeaderFooterImagePositionRight, file: images[".emz"], isFooter: true, firstPage: true, ext: ".emz"},
|
||||||
|
{position: HeaderFooterImagePositionLeft, file: images[".png"], ext: ".png"},
|
||||||
|
{position: HeaderFooterImagePositionCenter, file: images[".png"], ext: ".png"},
|
||||||
|
{position: HeaderFooterImagePositionRight, file: images[".png"], ext: ".png"},
|
||||||
|
{position: HeaderFooterImagePositionLeft, file: images[".tif"], isFooter: true, ext: ".tif"},
|
||||||
|
{position: HeaderFooterImagePositionCenter, file: images[".tif"], isFooter: true, ext: ".tif"},
|
||||||
|
{position: HeaderFooterImagePositionRight, file: images[".tif"], isFooter: true, ext: ".tif"},
|
||||||
|
} {
|
||||||
|
assert.NoError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||||
|
Position: opt.position,
|
||||||
|
File: opt.file,
|
||||||
|
IsFooter: opt.isFooter,
|
||||||
|
FirstPage: opt.firstPage,
|
||||||
|
Extension: opt.ext,
|
||||||
|
Width: "50pt",
|
||||||
|
Height: "32pt",
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
assert.NoError(t, f.SetCellValue(sheet, "A1", "Example"))
|
||||||
|
|
||||||
|
// Test add header footer image with not exist sheet
|
||||||
|
assert.EqualError(t, f.AddHeaderFooterImage("SheetN", nil), "sheet SheetN does not exist")
|
||||||
|
// Test add header footer image with unsupported file type
|
||||||
|
assert.Equal(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||||
|
Extension: "jpg",
|
||||||
|
}), ErrImgExt)
|
||||||
|
assert.NoError(t, f.SaveAs(wb))
|
||||||
|
assert.NoError(t, f.Close())
|
||||||
|
// Test change already exist header image with the different image
|
||||||
|
f, err := OpenFile(wb)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||||
|
File: images[".jpg"],
|
||||||
|
FirstPage: true,
|
||||||
|
Extension: ".jpg",
|
||||||
|
Width: "50pt",
|
||||||
|
Height: "32pt",
|
||||||
|
}))
|
||||||
|
assert.NoError(t, f.Save())
|
||||||
|
assert.NoError(t, f.Close())
|
||||||
|
|
||||||
|
// Test add header image with unsupported charset VML drawing
|
||||||
|
f, err = OpenFile(wb)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
f.Pkg.Store("xl/drawings/vmlDrawing1.vml", MacintoshCyrillicCharset)
|
||||||
|
assert.EqualError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||||
|
File: images[".jpg"],
|
||||||
|
Extension: ".jpg",
|
||||||
|
Width: "50pt",
|
||||||
|
Height: "32pt",
|
||||||
|
}), "XML syntax error on line 1: invalid UTF-8")
|
||||||
|
assert.NoError(t, f.Close())
|
||||||
|
// Test set legacy drawing header/footer with unsupported charset content types
|
||||||
|
f = NewFile()
|
||||||
|
f.ContentTypes = nil
|
||||||
|
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
|
||||||
|
assert.EqualError(t, f.AddHeaderFooterImage(sheet, &HeaderFooterImageOptions{
|
||||||
|
Extension: ".png",
|
||||||
|
File: images[".png"],
|
||||||
|
Width: "50pt",
|
||||||
|
Height: "32pt",
|
||||||
|
}), "XML syntax error on line 1: invalid UTF-8")
|
||||||
|
assert.NoError(t, f.Close())
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
18
xmlChart.go
18
xmlChart.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -336,6 +336,7 @@ type cCharts struct {
|
||||||
SplitPos *attrValInt `xml:"splitPos"`
|
SplitPos *attrValInt `xml:"splitPos"`
|
||||||
SerLines *attrValString `xml:"serLines"`
|
SerLines *attrValString `xml:"serLines"`
|
||||||
DLbls *cDLbls `xml:"dLbls"`
|
DLbls *cDLbls `xml:"dLbls"`
|
||||||
|
GapWidth *attrValInt `xml:"gapWidth"`
|
||||||
Shape *attrValString `xml:"shape"`
|
Shape *attrValString `xml:"shape"`
|
||||||
HoleSize *attrValInt `xml:"holeSize"`
|
HoleSize *attrValInt `xml:"holeSize"`
|
||||||
Smooth *attrValBool `xml:"smooth"`
|
Smooth *attrValBool `xml:"smooth"`
|
||||||
|
@ -483,6 +484,8 @@ type cNumCache struct {
|
||||||
// the specific formatting and positioning settings.
|
// the specific formatting and positioning settings.
|
||||||
type cDLbls struct {
|
type cDLbls struct {
|
||||||
NumFmt *cNumFmt `xml:"numFmt"`
|
NumFmt *cNumFmt `xml:"numFmt"`
|
||||||
|
SpPr *cSpPr `xml:"spPr"`
|
||||||
|
TxPr *cTxPr `xml:"txPr"`
|
||||||
DLblPos *attrValString `xml:"dLblPos"`
|
DLblPos *attrValString `xml:"dLblPos"`
|
||||||
ShowLegendKey *attrValBool `xml:"showLegendKey"`
|
ShowLegendKey *attrValBool `xml:"showLegendKey"`
|
||||||
ShowVal *attrValBool `xml:"showVal"`
|
ShowVal *attrValBool `xml:"showVal"`
|
||||||
|
@ -540,6 +543,7 @@ type ChartAxis struct {
|
||||||
Secondary bool
|
Secondary bool
|
||||||
Maximum *float64
|
Maximum *float64
|
||||||
Minimum *float64
|
Minimum *float64
|
||||||
|
Alignment Alignment
|
||||||
Font Font
|
Font Font
|
||||||
LogBase float64
|
LogBase float64
|
||||||
NumFmt ChartNumFmt
|
NumFmt ChartNumFmt
|
||||||
|
@ -583,6 +587,8 @@ type Chart struct {
|
||||||
ShowBlanksAs string
|
ShowBlanksAs string
|
||||||
BubbleSize int
|
BubbleSize int
|
||||||
HoleSize int
|
HoleSize int
|
||||||
|
GapWidth *uint
|
||||||
|
Overlap *int
|
||||||
order int
|
order int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,6 +612,13 @@ type ChartLine struct {
|
||||||
Width float64
|
Width float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChartDataLabel directly maps the format settings of the chart labels.
|
||||||
|
type ChartDataLabel struct {
|
||||||
|
Alignment Alignment
|
||||||
|
Font Font
|
||||||
|
Fill Fill
|
||||||
|
}
|
||||||
|
|
||||||
// ChartSeries directly maps the format settings of the chart series.
|
// ChartSeries directly maps the format settings of the chart series.
|
||||||
type ChartSeries struct {
|
type ChartSeries struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -615,5 +628,6 @@ type ChartSeries struct {
|
||||||
Fill Fill
|
Fill Fill
|
||||||
Line ChartLine
|
Line ChartLine
|
||||||
Marker ChartMarker
|
Marker ChartMarker
|
||||||
|
DataLabel ChartDataLabel
|
||||||
DataLabelPosition ChartDataLabelPositionType
|
DataLabelPosition ChartDataLabelPositionType
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
16
xmlStyles.go
16
xmlStyles.go
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -162,11 +162,13 @@ type xlsxBorder struct {
|
||||||
DiagonalDown bool `xml:"diagonalDown,attr,omitempty"`
|
DiagonalDown bool `xml:"diagonalDown,attr,omitempty"`
|
||||||
DiagonalUp bool `xml:"diagonalUp,attr,omitempty"`
|
DiagonalUp bool `xml:"diagonalUp,attr,omitempty"`
|
||||||
Outline bool `xml:"outline,attr,omitempty"`
|
Outline bool `xml:"outline,attr,omitempty"`
|
||||||
Left xlsxLine `xml:"left,omitempty"`
|
Left *xlsxLine `xml:"left"`
|
||||||
Right xlsxLine `xml:"right,omitempty"`
|
Right *xlsxLine `xml:"right"`
|
||||||
Top xlsxLine `xml:"top,omitempty"`
|
Top *xlsxLine `xml:"top"`
|
||||||
Bottom xlsxLine `xml:"bottom,omitempty"`
|
Bottom *xlsxLine `xml:"bottom"`
|
||||||
Diagonal xlsxLine `xml:"diagonal,omitempty"`
|
Diagonal *xlsxLine `xml:"diagonal"`
|
||||||
|
Vertical *xlsxLine `xml:"vertical"`
|
||||||
|
Horizontal *xlsxLine `xml:"horizontal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlsxCellStyles directly maps the cellStyles element. This element contains
|
// xlsxCellStyles directly maps the cellStyles element. This element contains
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2016 - 2024 The excelize Authors. All rights reserved. Use of
|
// Copyright 2016 - 2025 The excelize Authors. All rights reserved. Use of
|
||||||
// this source code is governed by a BSD-style license that can be found in
|
// this source code is governed by a BSD-style license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
//
|
//
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
// writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
|
||||||
// Supports complex components by high compatibility, and provided streaming
|
// Supports complex components by high compatibility, and provided streaming
|
||||||
// API for generating or reading data from a worksheet with huge amounts of
|
// API for generating or reading data from a worksheet with huge amounts of
|
||||||
// data. This library needs Go version 1.18 or later.
|
// data. This library needs Go version 1.20 or later.
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ type xlsxWorksheet struct {
|
||||||
ColBreaks *xlsxColBreaks `xml:"colBreaks"`
|
ColBreaks *xlsxColBreaks `xml:"colBreaks"`
|
||||||
CustomProperties *xlsxInnerXML `xml:"customProperties"`
|
CustomProperties *xlsxInnerXML `xml:"customProperties"`
|
||||||
CellWatches *xlsxInnerXML `xml:"cellWatches"`
|
CellWatches *xlsxInnerXML `xml:"cellWatches"`
|
||||||
IgnoredErrors *xlsxInnerXML `xml:"ignoredErrors"`
|
IgnoredErrors *xlsxIgnoredErrors `xml:"ignoredErrors"`
|
||||||
SmartTags *xlsxInnerXML `xml:"smartTags"`
|
SmartTags *xlsxInnerXML `xml:"smartTags"`
|
||||||
Drawing *xlsxDrawing `xml:"drawing"`
|
Drawing *xlsxDrawing `xml:"drawing"`
|
||||||
LegacyDrawing *xlsxLegacyDrawing `xml:"legacyDrawing"`
|
LegacyDrawing *xlsxLegacyDrawing `xml:"legacyDrawing"`
|
||||||
|
@ -679,6 +679,28 @@ type xlsxPicture struct {
|
||||||
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
|
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xlsxIgnoredError specifies a single ignored error for a range of cells.
|
||||||
|
type xlsxIgnoredError struct {
|
||||||
|
XMLName xml.Name `xml:"ignoredError"`
|
||||||
|
Sqref string `xml:"sqref,attr"`
|
||||||
|
EvalError bool `xml:"evalError,attr,omitempty"`
|
||||||
|
TwoDigitTextYear bool `xml:"twoDigitTextYear,attr,omitempty"`
|
||||||
|
NumberStoredAsText bool `xml:"numberStoredAsText,attr,omitempty"`
|
||||||
|
Formula bool `xml:"formula,attr,omitempty"`
|
||||||
|
FormulaRange bool `xml:"formulaRange,attr,omitempty"`
|
||||||
|
UnlockedFormula bool `xml:"unlockedFormula,attr,omitempty"`
|
||||||
|
EmptyCellReference bool `xml:"emptyCellReference,attr,omitempty"`
|
||||||
|
ListDataValidation bool `xml:"listDataValidation,attr,omitempty"`
|
||||||
|
CalculatedColumn bool `xml:"calculatedColumn,attr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxIgnoredErrors specifies a collection of ignored errors, by cell range.
|
||||||
|
type xlsxIgnoredErrors struct {
|
||||||
|
XMLName xml.Name `xml:"ignoredErrors"`
|
||||||
|
IgnoredError []xlsxIgnoredError `xml:"ignoredError"`
|
||||||
|
ExtLst *xlsxExtLst `xml:"extLst"`
|
||||||
|
}
|
||||||
|
|
||||||
// xlsxLegacyDrawing directly maps the legacyDrawing element in the namespace
|
// xlsxLegacyDrawing directly maps the legacyDrawing element in the namespace
|
||||||
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - A comment is a
|
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - A comment is a
|
||||||
// rich text note that is attached to, and associated with, a cell, separate
|
// rich text note that is attached to, and associated with, a cell, separate
|
||||||
|
@ -1006,6 +1028,9 @@ type PageLayoutOptions struct {
|
||||||
FitToWidth *int
|
FitToWidth *int
|
||||||
// BlackAndWhite specified print black and white.
|
// BlackAndWhite specified print black and white.
|
||||||
BlackAndWhite *bool
|
BlackAndWhite *bool
|
||||||
|
// PageOrder specifies the ordering of multiple pages. Values
|
||||||
|
// accepted: overThenDown and downThenOver
|
||||||
|
PageOrder *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ViewOptions directly maps the settings of sheet view.
|
// ViewOptions directly maps the settings of sheet view.
|
||||||
|
|
Loading…
Reference in New Issue