Full Code of qax-os/excelize for AI

master df428826c02b cached
115 files
3.4 MB
900.4k tokens
3163 symbols
1 requests
Download .txt
Showing preview only (3,601K chars total). Download the full file or copy to clipboard to get everything.
Repository: qax-os/excelize
Branch: master
Commit: df428826c02b
Files: 115
Total size: 3.4 MB

Directory structure:
gitextract_jqjalinp/

├── .github/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   └── feature_request.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── SECURITY.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── codeql-analysis.yml
│       └── go.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_zh.md
├── adjust.go
├── adjust_test.go
├── calc.go
├── calc_test.go
├── calcchain.go
├── calcchain_test.go
├── cell.go
├── cell_test.go
├── chart.go
├── chart_test.go
├── col.go
├── col_test.go
├── crypt.go
├── crypt_test.go
├── datavalidation.go
├── datavalidation_test.go
├── date.go
├── date_test.go
├── docProps.go
├── docProps_test.go
├── drawing.go
├── drawing_test.go
├── errors.go
├── errors_test.go
├── excelize.go
├── excelize_test.go
├── file.go
├── file_test.go
├── go.mod
├── go.sum
├── hsl.go
├── lib.go
├── lib_test.go
├── merge.go
├── merge_test.go
├── numfmt.go
├── numfmt_test.go
├── picture.go
├── picture_test.go
├── pivotTable.go
├── pivotTable_test.go
├── rows.go
├── rows_test.go
├── shape.go
├── shape_test.go
├── sheet.go
├── sheet_test.go
├── sheetpr.go
├── sheetpr_test.go
├── sheetview.go
├── sheetview_test.go
├── slicer.go
├── slicer_test.go
├── sparkline.go
├── sparkline_test.go
├── stream.go
├── stream_test.go
├── styles.go
├── styles_test.go
├── table.go
├── table_test.go
├── templates.go
├── test/
│   ├── BadWorkbook.xlsx
│   ├── Book1.xlsx
│   ├── CalcChain.xlsx
│   ├── MergeCell.xlsx
│   ├── OverflowNumericCell.xlsx
│   ├── SharedStrings.xlsx
│   ├── encryptAES.xlsx
│   ├── encryptSHA1.xlsx
│   └── images/
│       ├── excel.emf
│       ├── excel.emz
│       ├── excel.tif
│       ├── excel.wmf
│       └── excel.wmz
├── vml.go
├── vmlDrawing.go
├── vml_test.go
├── workbook.go
├── workbook_test.go
├── xmlApp.go
├── xmlCalcChain.go
├── xmlChart.go
├── xmlChartSheet.go
├── xmlComments.go
├── xmlContentTypes.go
├── xmlCore.go
├── xmlCustom.go
├── xmlDecodeDrawing.go
├── xmlDrawing.go
├── xmlMetaData.go
├── xmlPivotCache.go
├── xmlPivotTable.go
├── xmlSharedStrings.go
├── xmlSlicers.go
├── xmlStyles.go
├── xmlTable.go
├── xmlTheme.go
├── xmlWorkbook.go
└── xmlWorksheet.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others’ private information, such as a physical or email address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.

Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [xuri.me](https://xuri.me). All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.

Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.

### 2. Warning

Community Impact: A violation through a single incident or series of actions.

Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.

### 3. Temporary Ban

Community Impact: A serious violation of community standards, including sustained inappropriate behavior.

Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.

Consequence: A permanent ban from any sort of public interaction within the community.

## Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).

Community Impact Guidelines were inspired by Mozilla’s code of conduct enforcement ladder.

For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are available at [https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations).


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing to excelize

Want to hack on excelize? Awesome! This page contains information about reporting issues as well as some tips and
guidelines useful to experienced open source contributors. Finally, make sure
you read our [community guidelines](#community-guidelines) before you
start participating.

## Topics

* [Reporting Security Issues](#reporting-security-issues)
* [Design and Cleanup Proposals](#design-and-cleanup-proposals)
* [Reporting Issues](#reporting-other-issues)
* [Quick Contribution Tips and Guidelines](#quick-contribution-tips-and-guidelines)
* [Community Guidelines](#community-guidelines)

## Reporting security issues

The excelize maintainers take security seriously. If you discover a security
issue, please bring it to their attention right away!

Please **DO NOT** file a public issue, instead send your report privately to
[xuri.me](https://xuri.me).

Security reports are greatly appreciated and we will publicly thank you for them.
We currently do not offer a paid security bounty program, but are not
ruling it out in the future.

## Reporting other issues

A great way to contribute to the project is to send a detailed report when you
encounter an issue. We always appreciate a well-written, thorough bug report,
and will thank you for it!

Check that [our issue database](https://github.com/xuri/excelize/issues)
doesn't already include that problem or suggestion before submitting an issue.
If you find a match, you can use the "subscribe" button to get notified on
updates. Do *not* leave random "+1" or "I have this too" comments, as they
only clutter the discussion, and don't help resolving it. However, if you
have ways to reproduce the issue or have additional information that may help
resolving the issue, please leave a comment.

When reporting issues, always include the output of `go env`.

Also include the steps required to reproduce the problem if possible and
applicable. This information will help us review and fix your issue faster.
When sending lengthy log-files, consider posting them as a gist [https://gist.github.com](https://gist.github.com).
Don't forget to remove sensitive data from your logfiles before posting (you can
replace those parts with "REDACTED").

## Quick contribution tips and guidelines

This section gives the experienced contributor some tips and guidelines.

### Pull requests are always welcome

Not sure if that typo is worth a pull request? Found a bug and know how to fix
it? Do it! We will appreciate it. Any significant improvement should be
documented as [a GitHub issue](https://github.com/xuri/excelize/issues) before
anybody starts working on it.

We are always thrilled to receive pull requests. We do our best to process them
quickly. If your pull request is not accepted on the first try,
don't get discouraged!

### Design and cleanup proposals

You can propose new designs for existing excelize features. You can also design
entirely new features. We really appreciate contributors who want to refactor or
otherwise cleanup our project.

We try hard to keep excelize lean and focused. Excelize can't do everything for
everybody. This means that we might decide against incorporating a new feature.
However, there might be a way to implement that feature *on top of* excelize.

### Conventions

Fork the repository and make changes on your fork in a feature branch:

* If it's a bug fix branch, name it XXXX-something where XXXX is the number of
    the issue.
* If it's a feature branch, create an enhancement issue to announce
    your intentions, and name it XXXX-something where XXXX is the number of the
    issue.

Submit unit tests for your changes. Go has a great test framework built in; use
it! Take a look at existing tests for inspiration. Run the full test on your branch before
submitting a pull request.

Update the documentation when creating or modifying features. Test your
documentation changes for clarity, concision, and correctness, as well as a
clean documentation build.

Write clean code. Universally formatted code promotes ease of writing, reading,
and maintenance. Always run `gofmt -s -w file.go` on each changed file before
committing your changes. Most editors have plug-ins that do this automatically.

Pull request descriptions should be as clear as possible and include a reference
to all the issues that they address.

### Successful Changes

Before contributing large or high impact changes, make the effort to coordinate
with the maintainers of the project before submitting a pull request. This
prevents you from doing extra work that may or may not be merged.

Large PRs that are just submitted without any prior communication is unlikely
to be successful.

While pull requests are the methodology for submitting changes to code, changes
are much more likely to be accepted if they are accompanied by additional
engineering work. While we don't define this explicitly, most of these goals
are accomplished through the communication of the design goals and subsequent
solutions. Oftentimes, it helps to first state the problem before presenting
solutions.

Typically, the best methods of accomplishing this are to submit an issue,
stating the problem. This issue can include a problem statement and a
checklist with requirements. If solutions are proposed, alternatives should be
listed and eliminated. Even if the criteria for elimination of a solution is
frivolous, say so.

Larger changes typically work best with design documents. These are focused on
providing context to the design at the time the feature was conceived and can
inform future documentation contributions.

### Commit Messages

Commit messages must start with a capitalized and short summary
written in the imperative, followed by an optional, more detailed explanatory
text which is separated from the summary by an empty line.

Commit messages should follow best practices, including explaining the context
of the problem and how it was solved, including in caveats or follow-up changes
required. They should tell the story of the change and provide readers
understanding of what led to it.

In practice, the best approach to maintaining a nice commit message is to
leverage a `git add -p` and `git commit --amend` to formulate a solid
changeset. This allows one to piece together a change, as information becomes
available.

If you squash a series of commits, don't just submit that. Re-write the commit
message, as if the series of commits was a single stroke of brilliance.

That said, there is no requirement to have a single commit for a PR, as long as
each commit tells the story. For example, if there is a feature that requires a
package, it might make sense to have the package in a separate commit then have
a subsequent commit that uses it.

Remember, you're telling part of the story with the commit message. Don't make
your chapter weird.

### Review

Code review comments may be added to your pull request. Discuss, then make the
suggested modifications and push additional commits to your feature branch. Post
a comment after pushing. New commits show up in the pull request automatically,
but the reviewers are notified only when you comment.

Pull requests must be cleanly rebased on top of master without multiple branches
mixed into the PR.

**Git tip**: If your PR no longer merges cleanly, use `rebase master` in your
feature branch to update your pull request rather than `merge master`.

Before you make a pull request, squash your commits into logical units of work
using `git rebase -i` and `git push -f`. A logical unit of work is a consistent
set of patches that should be reviewed together: for example, upgrading the
version of a vendored dependency and taking advantage of its now available new
feature constitute two separate units of work. Implementing a new function and
calling it in another file constitute a single logical unit of work. The very
high majority of submissions should have a single commit, so if in doubt: squash
down to one.

After every commit, make sure the test passes. Include documentation
changes in the same pull request so that a revert would remove all traces of
the feature or fix.

Include an issue reference like `Closes #XXXX` or `Fixes #XXXX` in commits that
close an issue. Including references automatically closes the issue on a merge.

Please see the [Coding Style](#coding-style) for further guidelines.

### Merge approval

The excelize maintainers use LGTM (Looks Good To Me) in comments on the code review to
indicate acceptance.

### Sign your work

The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch or otherwise have the right to pass
it on as an open-source patch. The rules are pretty simple: if you can certify
the below (from [developercertificate.org](https://developercertificate.org)):

```text
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
```

Then you just add a line to every git commit message:

```text
Signed-off-by: Ri Xu https://xuri.me
```

Use your real name (sorry, no pseudonyms or anonymous contributions.)

If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.

### How can I become a maintainer

First, all maintainers have 3 things

* They share responsibility in the project's success.
* They have made a long-term, recurring time investment to improve the project.
* They spend that time doing whatever needs to be done, not necessarily what
 is the most interesting or fun.

Maintainers are often under-appreciated, because their work is harder to appreciate.
It's easy to appreciate a really cool and technically advanced feature. It's harder
to appreciate the absence of bugs, the slow but steady improvement in stability,
or the reliability of a release process. But those things distinguish a good
project from a great one.

Don't forget: being a maintainer is a time investment. Make sure you
will have time to make yourself available. You don't have to be a
maintainer to make a difference on the project!

If you want to become a maintainer, contact [xuri.me](https://xuri.me) and given an introduction of you.

## Community guidelines

We want to keep the community awesome, growing and collaborative. We need
your help to keep it that way. To help with this we've come up with some general
guidelines for the community as a whole:

* Be nice: Be courteous, respectful and polite to fellow community members:
  no regional, racial, gender, or other abuse will be tolerated. We like
  nice people way better than mean ones!

* Encourage diversity and participation: Make everyone in our community feel
  welcome, regardless of their background and the extent of their
  contributions, and do everything possible to encourage participation in
  our community.

* Keep it legal: Basically, don't get us in trouble. Share only content that
  you own, do not share private or sensitive information, and don't break
  the law.

* Stay on topic: Make sure that you are posting to the correct channel and
  avoid off-topic discussions. Remember when you update an issue or respond
  to an email you are potentially sending to a large number of people. Please
  consider this before you update. Also remember that nobody likes spam.

* Don't send email to the maintainers: There's no need to send email to the
  maintainers to ask them to investigate an issue or to take a look at a
  pull request. Instead of sending an email, GitHub mentions should be
  used to ping maintainers to review a pull request, a proposal or an
  issue.

### Guideline violations — 3 strikes method

The point of this section is not to find opportunities to punish people, but we
do need a fair way to deal with people who are making our community suck.

1. First occurrence: We'll give you a friendly, but public reminder that the
   behavior is inappropriate according to our guidelines.

2. Second occurrence: We will send you a private message with a warning that
   any additional violations will result in removal from the community.

3. Third occurrence: Depending on the violation, we may need to delete or ban
   your account.

**Notes:**

* Obvious spammers are banned on first occurrence. If we don't do this, we'll
  have spam all over the place.

* Violations are forgiven after 6 months of good behavior, and we won't hold a
  grudge.

* People who commit minor infractions will get some education, rather than
  hammering them in the 3 strikes process.

* The rules apply equally to everyone in the community, no matter how much
    you've contributed.

* Extreme violations of a threatening, abusive, destructive or illegal nature
    will be addressed immediately and are not subject to 3 strikes or forgiveness.

* Contact [xuri.me](https://xuri.me) to report abuse or appeal violations. In the case of
    appeals, we know that mistakes happen, and we'll work with you to come up with a
    fair solution if there has been a misunderstanding.

## Coding Style

Unless explicitly stated, we follow all coding guidelines from the Go
community. While some of these standards may seem arbitrary, they somehow seem
to result in a solid, consistent codebase.

It is possible that the code base does not currently comply with these
guidelines. We are not looking for a massive PR that fixes this, since that
goes against the spirit of the guidelines. All new contributions should make a
best effort to clean up and make the code base better than they left it.
Obviously, apply your best judgement. Remember, the goal here is to make the
code base easier for humans to navigate and understand. Always keep that in
mind when nudging others to comply.

The rules:

1. All code should be formatted with `gofmt -s`.
2. All code should pass the default levels of
   [`go vet`](https://pkg.go.dev/cmd/vet).
3. All code should follow the guidelines covered in [Effective
   Go](https://go.dev/doc/effective_go) and [Go Code Review
   Comments](https://github.com/golang/go/wiki/CodeReviewComments).
4. Comment the code. Tell us the why, the history and the context.
5. Document _all_ declarations and methods, even private ones. Declare
   expectations, caveats and anything else that may be important. If a type
   gets exported, having the comments already there will ensure it's ready.
6. Variable name length should be proportional to its context and no longer.
   `noCommaALongVariableNameLikeThisIsNotMoreClearWhenASimpleCommentWouldDo`.
   In practice, short methods will have short variable names and globals will
   have longer names.
7. No underscores in package names. If you need a compound name, step back,
   and re-examine why you need a compound name. If you still think you need a
   compound name, lose the underscore.
8. No utils or helpers packages. If a function is not general enough to
   warrant its own package, it has not been written generally enough to be a
   part of a util package. Just leave it unexported and well-documented.
9. All tests should run with `go test` and outside tooling should not be
   required. No, we don't need another unit testing framework. Assertion
   packages are acceptable if they provide _real_ incremental value.
10. Even though we call these "rules" above, they are actually just
    guidelines. Since you've read all the rules, you now know that.

If you are having trouble getting into the mood of idiomatic Go, we recommend
reading through [Effective Go](https://go.dev/doc/effective_go). The
[Go Blog](https://go.dev/blog/) is also a great resource. Drinking the
kool-aid is a lot easier than going thirsty.

## Code Review Comments and Effective Go Guidelines

[CodeLingo](https://www.codelingo.io) automatically checks every pull request against the following guidelines from [Effective Go](https://go.dev/doc/effective_go) and [Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).

### Package Comment

Every package should have a package comment, a block comment preceding the package clause.
For multi-file packages, the package comment only needs to be present in one file, and any one will do.
The package comment should introduce the package and provide information relevant to the package as a
whole. It will appear first on the godoc page and should set up the detailed documentation that follows.

### Single Method Interface Name

By convention, one-method interfaces are named by the method name plus an -er suffix
or similar modification to construct an agent noun: Reader, Writer, Formatter, CloseNotifier etc.

There are a number of such names and it's productive to honor them and the function names they capture.
Read, Write, Close, Flush, String and so on have canonical signatures and meanings. To avoid confusion,
don't give your method one of those names unless it has the same signature and meaning. Conversely,
if your type implements a method with the same meaning as a method on a well-known type, give it the
same name and signature; call your string-converter method String not ToString.

### Avoid Annotations in Comments

Comments do not need extra formatting such as banners of stars. The generated output
may not even be presented in a fixed-width font, so don't depend on spacing for alignment—godoc,
like gofmt, takes care of that. The comments are uninterpreted plain text, so HTML and other
annotations such as _this_ will reproduce verbatim and should not be used. One adjustment godoc
does do is to display indented text in a fixed-width font, suitable for program snippets.
The package comment for the fmt package uses this to good effect.

### Comment First Word as Subject

Doc comments work best as complete sentences, which allow a wide variety of automated presentations.
The first sentence should be a one-sentence summary that starts with the name being declared.

### Good Package Name

It's helpful if everyone using the package can use the same name
to refer to its contents, which implies that the package name should
be good: short, concise, and evocative. By convention, packages are
given lower case, single-word names; there should be no need for
underscores or mixedCaps. Err on the side of brevity, since everyone
using your package will be typing that name. And don't worry about
collisions a priori. The package name is only the default name for
imports; it need not be unique across all source code, and in the
rare case of a collision the importing package can choose a different
name to use locally. In any case, confusion is rare because the file
name in the import determines just which package is being used.

### Avoid Renaming Imports

Avoid renaming imports except to avoid a name collision; good package names
should not require renaming. In the event of collision, prefer to rename the
most local or project-specific import.

### Context as First Argument

Values of the context.Context type carry security credentials, tracing information,
deadlines, and cancellation signals across API and process boundaries. Go programs
pass Contexts explicitly along the entire function call chain from incoming RPCs
and HTTP requests to outgoing requests.

Most functions that use a Context should accept it as their first parameter.

### Do Not Discard Errors

Do not discard errors using _ variables. If a function returns an error,
check it to make sure the function succeeded. Handle the error, return it, or,
in truly exceptional situations, panic.

### Go Error Format

Error strings should not be capitalized (unless beginning with proper nouns
or acronyms) or end with punctuation, since they are usually printed following
other context. That is, use fmt.Errorf("something bad") not fmt.Errorf("Something bad"),
so that log.Printf("Reading %s: %v", filename, err) formats without a spurious
capital letter mid-message. This does not apply to logging, which is implicitly
line-oriented and not combined inside other messages.

### Use Crypto Rand

Do not use package math/rand to generate keys, even
throwaway ones. Unseeded, the generator is completely predictable.
Seeded with time.Nanoseconds(), there are just a few bits of entropy.
Instead, use crypto/rand's Reader, and if you need text, print to
hexadecimal or base64.


================================================
FILE: .github/FUNDING.yml
================================================
github: xuri
open_collective: excelize
patreon: xuri
ko_fi: xurime
liberapay: xuri
issuehunt: xuri
custom: https://www.paypal.com/paypalme/xuri

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
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


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
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


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
# PR Details

<!--- Provide a general summary of your changes in the Title above -->

## Description

<!--- Describe your changes in detail -->

## Related Issue

<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->

## How Has This Been Tested

<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- See how your change affects other areas of the code, etc. -->

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [ ] Docs change / refactoring / dependency upgrade
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the **CONTRIBUTING** document.
- [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed.


================================================
FILE: .github/SECURITY.md
================================================
# Security Policy

## Supported Versions

We will dive into any security-related issue as long as your Excelize version is still supported by us. When reporting an issue, include as much information as possible, but no need to fill fancy forms or answer tedious questions. Just tell us what you found, how to reproduce it, and any concerns you have about it. We will respond as soon as possible and follow up with any missing information.

## Reporting a Vulnerability

Please e-mail us directly at `xuri.me@gmail.com` or use the security issue template on GitHub. In general, public disclosure is made after the issue has been fully identified and a patch is ready to be released. A security issue gets the highest priority assigned and a reply regarding the vulnerability is given within a typical 24 hours. Thank you!


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
name: "CodeQL"

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]
  schedule:
    - cron: '0 6 * * 3'

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-24.04

    strategy:
      fail-fast: false
      matrix:
        language: ['go']

    steps:
    - name: Checkout repository
      uses: actions/checkout@v6

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v4
      with:
        languages: ${{ matrix.language }}

    - name: Autobuild
      uses: github/codeql-action/autobuild@v4

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v4


================================================
FILE: .github/workflows/go.yml
================================================
on: [push, pull_request]
name: build
jobs:

  test:
    strategy:
      matrix:
        go-version: [1.25.x, 1.26.x]
        os: [ubuntu-24.04, macos-15-intel, macos-26, windows-latest]
        targetplatform: [x86, x64]

    runs-on: ${{ matrix.os }}

    steps:

    - name: Install Go
      uses: actions/setup-go@v6
      with:
        go-version: ${{ matrix.go-version }}
        cache: false

    - name: Checkout code
      uses: actions/checkout@v6

    - name: Get dependencies
      run: |
        env GO111MODULE=on go vet ./...
    - name: Build
      run: go build -v .

    - name: Build on ARM
      if: runner.os == 'Linux'
      run: |
        GOARCH=arm GOARM=5 go build .
        GOARCH=arm GOARM=6 go build .
        GOARCH=arm GOARM=7 go build .
        GOARCH=arm64 go build .
        GOARCH=arm64 GOOS=android go build .

    - name: Test
      run: env GO111MODULE=on go test -v -timeout 60m -race ./... -coverprofile='coverage.txt' -covermode=atomic

    - name: Codecov
      uses: codecov/codecov-action@v5
      env:
        CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      with:
        files: coverage.txt
        flags: unittests
        name: codecov-umbrella


================================================
FILE: .gitignore
================================================
.DS_Store
.idea
*.json
*.out
*.test
~$*.xlsx
test/*.png
test/BadWorkbook.SaveAsEmptyStruct.xlsx
test/Encryption*.xlsx
test/excelize-*
test/Test*.xlam
test/Test*.xlsm
test/Test*.xlsx
test/Test*.xltm
test/Test*.xltx


================================================
FILE: LICENSE
================================================
BSD 3-Clause License

Copyright (c) 2016-2026 The excelize Authors.
Copyright (c) 2011-2017 Geoffrey J. Teale
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: README.md
================================================
<p align="center"><img width="650" src="./excelize.svg" alt="Excelize logo"></p>

<p align="center">
    <a href="https://github.com/xuri/excelize/actions/workflows/go.yml"><img src="https://github.com/xuri/excelize/actions/workflows/go.yml/badge.svg" alt="Build Status"></a>
    <a href="https://codecov.io/gh/qax-os/excelize"><img src="https://codecov.io/gh/qax-os/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
    <a href="https://goreportcard.com/report/github.com/xuri/excelize/v2"><img src="https://goreportcard.com/badge/github.com/xuri/excelize/v2" alt="Go Report Card"></a>
    <a href="https://pkg.go.dev/github.com/xuri/excelize/v2"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
    <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
    <a href="https://www.paypal.com/paypalme/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
</p>

# Excelize

## 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&trade; 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.25.0 or later. 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

### Installation

```bash
go get github.com/xuri/excelize
```

- If your packages are managed using [Go Modules](https://go.dev/blog/using-go-modules), please install with following command.

```bash
go get github.com/xuri/excelize/v2
```

### Create spreadsheet

Here is a minimal example usage that will create spreadsheet file.

```go
package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // Create a new sheet.
    index, err := f.NewSheet("Sheet2")
    if err != nil {
        fmt.Println(err)
        return
    }
    // Set value of a cell.
    f.SetCellValue("Sheet2", "A2", "Hello world.")
    f.SetCellValue("Sheet1", "B2", 100)
    // Set active sheet of the workbook.
    f.SetActiveSheet(index)
    // Save spreadsheet by the given path.
    if err := f.SaveAs("Book1.xlsx"); err != nil {
        fmt.Println(err)
    }
}
```

### Reading spreadsheet

The following constitutes the bare to read a spreadsheet document.

```go
package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"
)

func main() {
    f, err := excelize.OpenFile("Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer func() {
        // Close the spreadsheet.
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // Get value from cell by given worksheet name and cell reference.
    cell, err := f.GetCellValue("Sheet1", "B2")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(cell)
    // Get all the rows in the Sheet1.
    rows, err := f.GetRows("Sheet1")
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, row := range rows {
        for _, colCell := range row {
            fmt.Print(colCell, "\t")
        }
        fmt.Println()
    }
}
```

### Add chart to spreadsheet file

With Excelize chart generation and management is as easy as a few lines of code. You can build charts based on data in your worksheet or generate charts without any data in your worksheet at all.

<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p>

```go
package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    for idx, row := range [][]interface{}{
        {nil, "Apple", "Orange", "Pear"}, {"Small", 2, 3, 3},
        {"Normal", 5, 2, 4}, {"Large", 6, 7, 8},
    } {
        cell, err := excelize.CoordinatesToCellName(1, idx+1)
        if err != nil {
            fmt.Println(err)
            return
        }
        f.SetSheetRow("Sheet1", cell, &row)
    }
    if err := f.AddChart("Sheet1", "E1", &excelize.Chart{
        Type: excelize.Col3DClustered,
        Series: []excelize.ChartSeries{
            {
                Name:       "Sheet1!$A$2",
                Categories: "Sheet1!$B$1:$D$1",
                Values:     "Sheet1!$B$2:$D$2",
            },
            {
                Name:       "Sheet1!$A$3",
                Categories: "Sheet1!$B$1:$D$1",
                Values:     "Sheet1!$B$3:$D$3",
            },
            {
                Name:       "Sheet1!$A$4",
                Categories: "Sheet1!$B$1:$D$1",
                Values:     "Sheet1!$B$4:$D$4",
            }},
        Title: []excelize.RichTextRun{
            {
                Text: "Fruit 3D Clustered Column Chart",
            },
        },
    }); err != nil {
        fmt.Println(err)
        return
    }
    // Save spreadsheet by the given path.
    if err := f.SaveAs("Book1.xlsx"); err != nil {
        fmt.Println(err)
    }
}
```

### Add picture to spreadsheet file

```go
package main

import (
    "fmt"
    _ "image/gif"
    _ "image/jpeg"
    _ "image/png"

    "github.com/xuri/excelize/v2"
)

func main() {
    f, err := excelize.OpenFile("Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer func() {
        // Close the spreadsheet.
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // Insert a picture.
    if err := f.AddPicture("Sheet1", "A2", "image.png", nil); err != nil {
        fmt.Println(err)
    }
    // Insert a picture to worksheet with scaling.
    if err := f.AddPicture("Sheet1", "D2", "image.jpg",
        &excelize.GraphicOptions{ScaleX: 0.5, ScaleY: 0.5}); err != nil {
        fmt.Println(err)
    }
    // Insert a picture offset in the cell with printing support.
    enable, disable := true, false
    if err := f.AddPicture("Sheet1", "H2", "image.gif",
        &excelize.GraphicOptions{
            PrintObject:     &enable,
            LockAspectRatio: false,
            OffsetX:         15,
            OffsetY:         10,
            Locked:          &disable,
        }); err != nil {
        fmt.Println(err)
    }
    // Save the spreadsheet with the origin path.
    if err = f.Save(); err != nil {
        fmt.Println(err)
    }
}
```

## Contributing

Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change. XML is compliant with [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](https://www.ecma-international.org/publications-and-standards/standards/ecma-376/).

## Licenses

This program is under the terms of the BSD 3-Clause License. See [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause).

The Excel logo is a trademark of [Microsoft Corporation](https://aka.ms/trademarks-usage). This artwork is an adaptation.

The Go gopher was created by [Renee French](https://go.dev/doc/gopher/README). Licensed under the [Creative Commons 4.0 Attributions license](http://creativecommons.org/licenses/by/4.0/).

## Gold Sponsors

<a href="https://www.gravityclimate.com" alt="Gravity"><img width="120" src="https://xuri.me/excelize/images/vendor/gravityclimate.com.svg" alt="Gravity"></a>


================================================
FILE: README_zh.md
================================================
<p align="center"><img width="650" src="./excelize.svg" alt="Excelize logo"></p>

<p align="center">
    <a href="https://github.com/xuri/excelize/actions/workflows/go.yml"><img src="https://github.com/xuri/excelize/actions/workflows/go.yml/badge.svg" alt="Build Status"></a>
    <a href="https://codecov.io/gh/qax-os/excelize"><img src="https://codecov.io/gh/qax-os/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
    <a href="https://goreportcard.com/report/github.com/xuri/excelize/v2"><img src="https://goreportcard.com/badge/github.com/xuri/excelize/v2" alt="Go Report Card"></a>
    <a href="https://pkg.go.dev/github.com/xuri/excelize/v2"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
    <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
    <a href="https://www.paypal.com/paypalme/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
</p>

# Excelize

## 简介

Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel&trade; 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写函数,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.25.0 或更高版本。完整的使用文档请访问 [go.dev](https://pkg.go.dev/github.com/xuri/excelize/v2) 或查看 [参考文档](https://xuri.me/excelize/)。

## 快速上手

### 安装

```bash
go get github.com/xuri/excelize
```

- 如果您使用 [Go Modules](https://go.dev/blog/using-go-modules) 管理软件包,请使用下面的命令来安装最新版本。

```bash
go get github.com/xuri/excelize/v2
```

### 创建 Excel 文档

下面是一个创建 Excel 文档的简单例子:

```go
package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // 创建一个工作表
    index, err := f.NewSheet("Sheet2")
    if err != nil {
        fmt.Println(err)
        return
    }
    // 设置单元格的值
    f.SetCellValue("Sheet2", "A2", "Hello world.")
    f.SetCellValue("Sheet1", "B2", 100)
    // 设置工作簿的默认工作表
    f.SetActiveSheet(index)
    // 根据指定路径保存文件
    if err := f.SaveAs("Book1.xlsx"); err != nil {
        fmt.Println(err)
    }
}
```

### 读取 Excel 文档

下面是读取 Excel 文档的例子:

```go
package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"
)

func main() {
    f, err := excelize.OpenFile("Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer func() {
        // 关闭工作簿
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // 获取工作表中指定单元格的值
    cell, err := f.GetCellValue("Sheet1", "B2")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(cell)
    // 获取 Sheet1 上所有单元格
    rows, err := f.GetRows("Sheet1")
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, row := range rows {
        for _, colCell := range row {
            fmt.Print(colCell, "\t")
        }
        fmt.Println()
    }
}
```

### 在 Excel 文档中创建图表

使用 Excelize 生成图表十分简单,仅需几行代码。您可以根据工作表中的已有数据构建图表,或向工作表中添加数据并创建图表。

<p align="center"><img width="650" src="./test/images/chart.png" alt="使用 Excelize 在 Excel 电子表格文档中创建图表"></p>

```go
package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    for idx, row := range [][]interface{}{
        {nil, "Apple", "Orange", "Pear"}, {"Small", 2, 3, 3},
        {"Normal", 5, 2, 4}, {"Large", 6, 7, 8},
    } {
        cell, err := excelize.CoordinatesToCellName(1, idx+1)
        if err != nil {
            fmt.Println(err)
            return
        }
        f.SetSheetRow("Sheet1", cell, &row)
    }
    if err := f.AddChart("Sheet1", "E1", &excelize.Chart{
        Type: excelize.Col3DClustered,
        Series: []excelize.ChartSeries{
            {
                Name:       "Sheet1!$A$2",
                Categories: "Sheet1!$B$1:$D$1",
                Values:     "Sheet1!$B$2:$D$2",
            },
            {
                Name:       "Sheet1!$A$3",
                Categories: "Sheet1!$B$1:$D$1",
                Values:     "Sheet1!$B$3:$D$3",
            },
            {
                Name:       "Sheet1!$A$4",
                Categories: "Sheet1!$B$1:$D$1",
                Values:     "Sheet1!$B$4:$D$4",
            }},
        Title: []excelize.RichTextRun{
            {
                Text: "Fruit 3D Clustered Column Chart",
            },
        },
    }); err != nil {
        fmt.Println(err)
        return
    }
    // 根据指定路径保存文件
    if err := f.SaveAs("Book1.xlsx"); err != nil {
        fmt.Println(err)
    }
}
```

### 向 Excel 文档中插入图片

```go
package main

import (
    "fmt"
    _ "image/gif"
    _ "image/jpeg"
    _ "image/png"

    "github.com/xuri/excelize/v2"
)

func main() {
    f, err := excelize.OpenFile("Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer func() {
        // 关闭工作簿
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // 插入图片
    if err := f.AddPicture("Sheet1", "A2", "image.png", nil); err != nil {
        fmt.Println(err)
    }
    // 在工作表中插入图片,并设置图片的缩放比例
    if err := f.AddPicture("Sheet1", "D2", "image.jpg",
        &excelize.GraphicOptions{ScaleX: 0.5, ScaleY: 0.5}); err != nil {
        fmt.Println(err)
    }
    // 在工作表中插入图片,并设置图片的打印属性
    enable, disable := true, false
    if err := f.AddPicture("Sheet1", "H2", "image.gif",
        &excelize.GraphicOptions{
            PrintObject:     &enable,
            LockAspectRatio: false,
            OffsetX:         15,
            OffsetY:         10,
            Locked:          &disable,
        }); err != nil {
        fmt.Println(err)
    }
    // 保存工作簿
    if err = f.Save(); err != nil {
        fmt.Println(err)
    }
}
```

## 社区合作

欢迎您为此项目贡献代码,提出建议或问题、修复 Bug 以及参与讨论对新功能的想法。 XML 符合标准: [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](https://www.ecma-international.org/publications-and-standards/standards/ecma-376/)。

## 开源许可

本项目遵循 BSD 3-Clause 开源许可协议,访问 [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) 查看许可协议文件。

Excel 徽标是 [Microsoft Corporation](https://aka.ms/trademarks-usage) 的商标,项目的图片是一种改编。

Go gopher 由 [Renee French](https://go.dev/doc/gopher/README) 创作,遵循 [Creative Commons 4.0 Attributions license](http://creativecommons.org/licenses/by/4.0/) 创作共用授权条款。

## 金牌赞助商

<a href="https://www.gravityclimate.com" alt="Gravity"><img width="120" src="https://xuri.me/excelize/images/vendor/gravityclimate.com.svg" alt="Gravity"></a>


================================================
FILE: adjust.go
================================================
// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to 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.25.0 or later.

package excelize

import (
	"bytes"
	"encoding/xml"
	"io"
	"strconv"
	"strings"
	"unicode"

	"github.com/xuri/efp"
)

type adjustDirection bool

const (
	columns adjustDirection = false
	rows    adjustDirection = true
)

// adjustHelperFunc defines functions to adjust helper.
var adjustHelperFunc = [9]func(*File, *xlsxWorksheet, string, adjustDirection, int, int, int) error{
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustConditionalFormats(ws, sheet, dir, num, offset, sheetID)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustDataValidations(ws, sheet, dir, num, offset, sheetID)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustDefinedNames(sheet, dir, num, offset)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustDrawings(ws, sheet, dir, num, offset)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustMergeCells(ws, sheet, dir, num, offset, sheetID)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustAutoFilter(ws, sheet, dir, num, offset, sheetID)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustCalcChain(ws, sheet, dir, num, offset, sheetID)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustTable(ws, sheet, dir, num, offset, sheetID)
	},
	func(f *File, ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
		return f.adjustVolatileDeps(ws, sheet, dir, num, offset, sheetID)
	},
}

// adjustHelper provides a function to adjust rows and columns dimensions,
// hyperlinks, merged cells and auto filter when inserting or deleting rows or
// columns.
//
// sheet: Worksheet name that we're editing
// column: Index number of the column we're inserting/deleting before
// row: Index number of the row we're inserting/deleting before
// offset: Number of rows/column to insert/delete negative values indicate deletion
//
// TODO: adjustComments, adjustPageBreaks, adjustProtectedCells
func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
	ws, err := f.workSheetReader(sheet)
	if err != nil {
		return err
	}
	f.clearCalcCache()
	sheetID := f.getSheetID(sheet)
	if dir == rows {
		err = f.adjustRowDimensions(sheet, ws, num, offset)
	} else {
		err = f.adjustColDimensions(sheet, ws, num, offset)
	}
	if err != nil {
		return err
	}
	f.adjustHyperlinks(ws, sheet, dir, num, offset)
	ws.checkSheet()
	_ = ws.checkRow()
	for _, fn := range adjustHelperFunc {
		if err := fn(f, ws, sheet, dir, num, offset, sheetID); err != nil {
			return err
		}
	}
	if ws.MergeCells != nil && len(ws.MergeCells.Cells) == 0 {
		ws.MergeCells = nil
	}
	return nil
}

// adjustCols provides a function to update column style when inserting or
// deleting columns.
func (f *File) adjustCols(ws *xlsxWorksheet, col, offset int) error {
	if ws.Cols == nil {
		return nil
	}
	for i := 0; i < len(ws.Cols.Col); i++ {
		if offset > 0 {
			if ws.Cols.Col[i].Min >= col {
				if ws.Cols.Col[i].Min += offset; ws.Cols.Col[i].Min > MaxColumns {
					ws.Cols.Col = append(ws.Cols.Col[:i], ws.Cols.Col[i+1:]...)
					i--
					continue
				}
			}
			if ws.Cols.Col[i].Max >= col || ws.Cols.Col[i].Max+1 == col {
				if ws.Cols.Col[i].Max += offset; ws.Cols.Col[i].Max > MaxColumns {
					ws.Cols.Col[i].Max = MaxColumns
				}
			}
			continue
		}
		if ws.Cols.Col[i].Min == col && ws.Cols.Col[i].Max == col {
			ws.Cols.Col = append(ws.Cols.Col[:i], ws.Cols.Col[i+1:]...)
			i--
			continue
		}
		if ws.Cols.Col[i].Min > col {
			ws.Cols.Col[i].Min += offset
		}
		if ws.Cols.Col[i].Max >= col {
			ws.Cols.Col[i].Max += offset
		}
	}
	if len(ws.Cols.Col) == 0 {
		ws.Cols = nil
	}
	return nil
}

// adjustColDimensions provides a function to update column dimensions when
// inserting or deleting rows or columns.
func (f *File) adjustColDimensions(sheet string, ws *xlsxWorksheet, col, offset int) error {
	for rowIdx := range ws.SheetData.Row {
		for _, v := range ws.SheetData.Row[rowIdx].C {
			if cellCol, _, _ := CellNameToCoordinates(v.R); col <= cellCol {
				if newCol := cellCol + offset; newCol > 0 && newCol > MaxColumns {
					return ErrColumnNumber
				}
			}
		}
	}
	for _, sheetN := range f.GetSheetList() {
		worksheet, err := f.workSheetReader(sheetN)
		if err != nil {
			if err.Error() == newNotWorksheetError(sheetN).Error() {
				continue
			}
			return err
		}
		for rowIdx := range worksheet.SheetData.Row {
			for colIdx, v := range worksheet.SheetData.Row[rowIdx].C {
				if cellCol, cellRow, _ := CellNameToCoordinates(v.R); sheetN == sheet && col <= cellCol {
					if newCol := cellCol + offset; newCol > 0 {
						worksheet.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
					}
				}
				if err := f.adjustFormula(sheet, sheetN, &worksheet.SheetData.Row[rowIdx].C[colIdx], columns, col, offset, false); err != nil {
					return err
				}
			}
		}
	}
	return f.adjustCols(ws, col, offset)
}

// adjustRowDimensions provides a function to update row dimensions when
// inserting or deleting rows or columns.
func (f *File) adjustRowDimensions(sheet string, ws *xlsxWorksheet, row, offset int) error {
	for _, sheetN := range f.GetSheetList() {
		if sheetN == sheet {
			continue
		}
		worksheet, err := f.workSheetReader(sheetN)
		if err != nil {
			if err.Error() == newNotWorksheetError(sheetN).Error() {
				continue
			}
			return err
		}
		numOfRows := len(worksheet.SheetData.Row)
		for i := 0; i < numOfRows; i++ {
			r := &worksheet.SheetData.Row[i]
			if err = f.adjustSingleRowFormulas(sheet, sheetN, r, row, offset, false); err != nil {
				return err
			}
		}
	}
	totalRows := len(ws.SheetData.Row)
	if totalRows == 0 {
		return nil
	}
	lastRow := &ws.SheetData.Row[totalRows-1]
	if newRow := lastRow.R + offset; lastRow.R >= row && newRow > 0 && newRow > TotalRows {
		return ErrMaxRows
	}
	numOfRows := len(ws.SheetData.Row)
	for i := 0; i < numOfRows; i++ {
		r := &ws.SheetData.Row[i]
		if newRow := r.R + offset; r.R >= row && newRow > 0 {
			r.adjustSingleRowDimensions(offset)
		}
		if err := f.adjustSingleRowFormulas(sheet, sheet, r, row, offset, false); err != nil {
			return err
		}
	}
	return nil
}

// adjustSingleRowDimensions provides a function to adjust single row dimensions.
func (r *xlsxRow) adjustSingleRowDimensions(offset int) {
	r.R += offset
	for i, col := range r.C {
		colName, _, _ := SplitCellName(col.R)
		r.C[i].R, _ = JoinCellName(colName, r.R)
	}
}

// adjustSingleRowFormulas provides a function to adjust single row formulas.
func (f *File) adjustSingleRowFormulas(sheet, sheetN string, r *xlsxRow, num, offset int, si bool) error {
	for i := 0; i < len(r.C); i++ {
		if err := f.adjustFormula(sheet, sheetN, &r.C[i], rows, num, offset, si); err != nil {
			return err
		}
	}
	return nil
}

// adjustCellRef provides a function to adjust cell reference.
func (f *File) adjustCellRef(cellRef string, dir adjustDirection, num, offset int) (string, error) {
	var SQRef []string
	applyOffset := func(coordinates []int, idx1, idx2, maxVal int) []int {
		if coordinates[idx1] >= num {
			coordinates[idx1] += offset
		}
		if coordinates[idx2] >= num {
			if coordinates[idx2] += offset; coordinates[idx2] > maxVal {
				coordinates[idx2] = maxVal
			}
		}
		return coordinates
	}
	for _, ref := range strings.Split(cellRef, " ") {
		if !strings.Contains(ref, ":") {
			ref += ":" + ref
		}
		coordinates, err := rangeRefToCoordinates(ref)
		if err != nil {
			return "", err
		}
		if dir == columns {
			if offset < 0 && coordinates[0] == coordinates[2] && num == coordinates[0] {
				continue
			}
			coordinates = applyOffset(coordinates, 0, 2, MaxColumns)
		} else {
			if offset < 0 && coordinates[1] == coordinates[3] && num == coordinates[1] {
				continue
			}
			coordinates = applyOffset(coordinates, 1, 3, TotalRows)
		}
		if ref, err = coordinatesToRangeRef(coordinates); err != nil {
			return "", err
		}
		SQRef = append(SQRef, ref)
	}
	return strings.Join(SQRef, " "), nil
}

// adjustFormula provides a function to adjust formula reference and shared
// formula reference.
func (f *File) adjustFormula(sheet, sheetN string, cell *xlsxC, dir adjustDirection, num, offset int, si bool) error {
	var err error
	if cell.f != "" {
		if cell.f, err = f.adjustFormulaRef(sheet, sheetN, cell.f, false, dir, num, offset); err != nil {
			return err
		}
	}
	if cell.F == nil {
		return nil
	}
	if cell.F.Ref != "" && sheet == sheetN {
		if cell.F.Ref, err = f.adjustCellRef(cell.F.Ref, dir, num, offset); err != nil {
			return err
		}
		if si && cell.F.Si != nil {
			cell.F.Si = intPtr(*cell.F.Si + 1)
		}
	}
	if cell.F.Content != "" {
		if cell.F.Content, err = f.adjustFormulaRef(sheet, sheetN, cell.F.Content, false, dir, num, offset); err != nil {
			return err
		}
	}
	return nil
}

// escapeSheetName enclose sheet name in single quotation marks if the giving
// worksheet name includes spaces or non-alphabetical characters.
func escapeSheetName(name string) string {
	if strings.IndexFunc(name, func(r rune) bool {
		return !unicode.IsLetter(r) && !unicode.IsNumber(r)
	}) != -1 {
		return "'" + strings.ReplaceAll(name, "'", "''") + "'"
	}
	return name
}

// adjustFormulaColumnName adjust column name in the formula reference.
func adjustFormulaColumnName(name, operand string, abs, keepRelative bool, dir adjustDirection, num, offset int) (string, string, bool, error) {
	if name == "" || (!abs && keepRelative) {
		return "", operand + name, abs, nil
	}
	col, err := ColumnNameToNumber(name)
	if err != nil {
		return "", operand, false, err
	}
	if dir == columns && col >= num {
		if col += offset; col < 1 {
			col = 1
		}
		colName, err := ColumnNumberToName(col)
		return "", operand + colName, false, err
	}
	return "", operand + name, false, nil
}

// adjustFormulaRowNumber adjust row number in the formula reference.
func adjustFormulaRowNumber(name, operand string, abs, keepRelative bool, dir adjustDirection, num, offset int) (string, string, bool, error) {
	if name == "" || (!abs && keepRelative) {
		return "", operand + name, abs, nil
	}
	row, _ := strconv.Atoi(name)
	if dir == rows && row >= num {
		if row += offset; row < 1 {
			row = 1
		}
		if row > TotalRows {
			return "", operand + name, false, ErrMaxRows
		}
		return "", operand + strconv.Itoa(row), false, nil
	}
	return "", operand + name, false, nil
}

// adjustFormulaOperandRef adjust cell reference in the operand tokens for the formula.
func adjustFormulaOperandRef(row, col, operand string, abs, keepRelative bool, dir adjustDirection, num int, offset int) (string, string, string, bool, error) {
	var err error
	col, operand, abs, err = adjustFormulaColumnName(col, operand, abs, keepRelative, dir, num, offset)
	if err != nil {
		return row, col, operand, abs, err
	}
	row, operand, abs, err = adjustFormulaRowNumber(row, operand, abs, keepRelative, dir, num, offset)
	return row, col, operand, abs, err
}

// adjustFormulaOperand adjust range operand tokens for the formula.
func (f *File) adjustFormulaOperand(sheet, sheetN string, keepRelative bool, token efp.Token, dir adjustDirection, num int, offset int) (string, error) {
	var (
		err                          error
		abs                          bool
		sheetName, col, row, operand string
		cell                         = token.TValue
		tokens                       = strings.Split(token.TValue, "!")
	)
	if len(tokens) == 2 { // have a worksheet
		sheetName, cell = tokens[0], tokens[1]
		operand = escapeSheetName(sheetName) + "!"
	}
	if sheetName == "" {
		sheetName = sheetN
	}
	if sheet != sheetName {
		return operand + cell, err
	}
	for _, r := range cell {
		if r == '$' {
			if col, operand, _, err = adjustFormulaColumnName(col, operand, abs, keepRelative, dir, num, offset); err != nil {
				return operand, err
			}
			abs = true
			operand += string(r)
			continue
		}
		if ('A' <= r && r <= 'Z') || ('a' <= r && r <= 'z') {
			col += string(r)
			continue
		}
		if '0' <= r && r <= '9' {
			row += string(r)
			col, operand, abs, err = adjustFormulaColumnName(col, operand, abs, keepRelative, dir, num, offset)
			if err != nil {
				return operand, err
			}
			continue
		}
		if row, col, operand, abs, err = adjustFormulaOperandRef(row, col, operand, abs, keepRelative, dir, num, offset); err != nil {
			return operand, err
		}
		operand += string(r)
	}
	_, _, operand, _, err = adjustFormulaOperandRef(row, col, operand, abs, keepRelative, dir, num, offset)
	return operand, err
}

// adjustFormulaRef returns adjusted formula by giving adjusting direction and
// the base number of column or row, and offset.
func (f *File) adjustFormulaRef(sheet, sheetN, formula string, keepRelative bool, dir adjustDirection, num, offset int) (string, error) {
	var (
		val          string
		definedNames []string
		ps           = efp.ExcelParser()
	)
	for _, definedName := range f.GetDefinedName() {
		if definedName.Scope == "Workbook" || definedName.Scope == sheet {
			definedNames = append(definedNames, definedName.Name)
		}
	}
	for _, token := range ps.Parse(formula) {
		if token.TType == efp.TokenTypeUnknown {
			val = formula
			break
		}
		if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeRange {
			if inStrSlice(definedNames, token.TValue, true) != -1 {
				val += token.TValue
				continue
			}
			if strings.ContainsAny(token.TValue, "[]") {
				val += token.TValue
				continue
			}
			operand, err := f.adjustFormulaOperand(sheet, sheetN, keepRelative, token, dir, num, offset)
			if err != nil {
				return val, err
			}
			val += operand
			continue
		}
		if paren := transformParenthesesToken(token); paren != "" {
			val += transformParenthesesToken(token)
			continue
		}
		if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText {
			val += string(efp.QuoteDouble) + strings.ReplaceAll(token.TValue, "\"", "\"\"") + string(efp.QuoteDouble)
			continue
		}
		val += token.TValue
	}
	return val, nil
}

// transformParenthesesToken returns formula part with parentheses by given
// token.
func transformParenthesesToken(token efp.Token) string {
	if isFunctionStartToken(token) || isBeginParenthesesToken(token) {
		return token.TValue + string(efp.ParenOpen)
	}
	if isFunctionStopToken(token) || isEndParenthesesToken(token) {
		return token.TValue + string(efp.ParenClose)
	}
	return ""
}

// adjustRangeSheetName returns replaced range reference by given source and
// target sheet name.
func adjustRangeSheetName(rng, source, target string) string {
	source = escapeSheetName(source)
	cellRefs := strings.Split(rng, ",")
	for i, cellRef := range cellRefs {
		rangeRefs := strings.Split(cellRef, ":")
		for j, rangeRef := range rangeRefs {
			parts := strings.Split(rangeRef, "!")
			for k, part := range parts {
				if strings.TrimPrefix(strings.TrimSuffix(part, "'"), "'") == source {
					part = escapeSheetName(target)
				}
				parts[k] = part
			}
			rangeRefs[j] = strings.Join(parts, "!")
		}
		cellRefs[i] = strings.Join(rangeRefs, ":")
	}
	return strings.Join(cellRefs, ",")
}

// arrayFormulaOperandToken defines meta fields for transforming the array
// formula to the normal formula.
type arrayFormulaOperandToken struct {
	operandTokenIndex, topLeftCol, topLeftRow, bottomRightCol, bottomRightRow int
	sheetName, sourceCellRef, targetCellRef                                   string
}

// setCoordinates convert each corner cell reference in the array formula cell
// range to the coordinate number.
func (af *arrayFormulaOperandToken) setCoordinates() error {
	for i, ref := range strings.Split(af.sourceCellRef, ":") {
		cellRef, col, row, err := parseRef(ref)
		if err != nil {
			return err
		}
		var c, r int
		if col {
			if cellRef.Row = TotalRows; i == 0 {
				cellRef.Row = 1
			}
		}
		if row {
			if cellRef.Col = MaxColumns; i == 0 {
				cellRef.Col = 1
			}
		}
		if c, r = cellRef.Col, cellRef.Row; cellRef.Sheet != "" {
			af.sheetName = cellRef.Sheet + "!"
		}
		if af.topLeftCol == 0 || c < af.topLeftCol {
			af.topLeftCol = c
		}
		if af.topLeftRow == 0 || r < af.topLeftRow {
			af.topLeftRow = r
		}
		if c > af.bottomRightCol {
			af.bottomRightCol = c
		}
		if r > af.bottomRightRow {
			af.bottomRightRow = r
		}
	}
	return nil
}

// transformArrayFormula transforms an array formula to the normal formula by
// giving a formula tokens list and formula operand tokens list.
func transformArrayFormula(tokens []efp.Token, afs []arrayFormulaOperandToken) string {
	var val string
	for i, token := range tokens {
		var skip bool
		for _, af := range afs {
			if af.operandTokenIndex == i {
				val += af.sheetName + af.targetCellRef
				skip = true
				break
			}
		}
		if skip {
			continue
		}
		if paren := transformParenthesesToken(token); paren != "" {
			val += transformParenthesesToken(token)
			continue
		}
		if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText {
			val += string(efp.QuoteDouble) + strings.ReplaceAll(token.TValue, "\"", "\"\"") + string(efp.QuoteDouble)
			continue
		}
		val += token.TValue
	}
	return val
}

// getArrayFormulaTokens returns parsed formula token and operand related token
// list for in array formula.
func getArrayFormulaTokens(sheet, formula string, definedNames []DefinedName) ([]efp.Token, []arrayFormulaOperandToken, error) {
	var (
		ps                        = efp.ExcelParser()
		tokens                    = ps.Parse(formula)
		arrayFormulaOperandTokens []arrayFormulaOperandToken
	)
	for i, token := range tokens {
		if token.TSubType == efp.TokenSubTypeRange && token.TType == efp.TokenTypeOperand {
			tokenVal := token.TValue
			for _, definedName := range definedNames {
				if (definedName.Scope == "Workbook" || definedName.Scope == sheet) && definedName.Name == tokenVal {
					tokenVal = definedName.RefersTo
				}
			}
			if len(strings.Split(tokenVal, ":")) > 1 {
				arrayFormulaOperandToken := arrayFormulaOperandToken{
					operandTokenIndex: i,
					sourceCellRef:     tokenVal,
				}
				if err := arrayFormulaOperandToken.setCoordinates(); err != nil {
					return tokens, arrayFormulaOperandTokens, err
				}
				arrayFormulaOperandTokens = append(arrayFormulaOperandTokens, arrayFormulaOperandToken)
			}
		}
	}
	return tokens, arrayFormulaOperandTokens, nil
}

// adjustHyperlinks provides a function to update hyperlinks when inserting or
// deleting rows or columns.
func (f *File) adjustHyperlinks(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset int) {
	// short path
	if ws.Hyperlinks == nil || len(ws.Hyperlinks.Hyperlink) == 0 {
		return
	}

	// order is important
	if offset < 0 {
		for i := len(ws.Hyperlinks.Hyperlink) - 1; i >= 0; i-- {
			linkData := ws.Hyperlinks.Hyperlink[i]
			colNum, rowNum, _ := CellNameToCoordinates(linkData.Ref)

			if (dir == rows && num == rowNum) || (dir == columns && num == colNum) {
				f.deleteSheetRelationships(sheet, linkData.RID)
				if len(ws.Hyperlinks.Hyperlink) > 1 {
					ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink[:i],
						ws.Hyperlinks.Hyperlink[i+1:]...)
				} else {
					ws.Hyperlinks = nil
				}
			}
		}
	}
	if ws.Hyperlinks == nil {
		return
	}
	for i := range ws.Hyperlinks.Hyperlink {
		link := &ws.Hyperlinks.Hyperlink[i] // get reference
		link.Ref, _ = f.adjustFormulaRef(sheet, sheet, link.Ref, false, dir, num, offset)
	}
}

// adjustTable provides a function to update the table when inserting or
// deleting rows or columns.
func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	if ws.TableParts == nil || len(ws.TableParts.TableParts) == 0 {
		return nil
	}
	for idx := 0; idx < len(ws.TableParts.TableParts); idx++ {
		tbl := ws.TableParts.TableParts[idx]
		target := f.getSheetRelationshipsTargetByID(sheet, tbl.RID)
		tableXML := strings.ReplaceAll(target, "..", "xl")
		content, ok := f.Pkg.Load(tableXML)
		if !ok {
			continue
		}
		t := xlsxTable{}
		if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(content.([]byte)))).
			Decode(&t); err != nil && err != io.EOF {
			return err
		}
		coordinates, err := rangeRefToCoordinates(t.Ref)
		if err != nil {
			return err
		}
		// Remove the table when deleting the header row of the table
		if dir == rows && num == coordinates[0] && offset == -1 {
			ws.TableParts.TableParts = append(ws.TableParts.TableParts[:idx], ws.TableParts.TableParts[idx+1:]...)
			ws.TableParts.Count = len(ws.TableParts.TableParts)
			idx--
			continue
		}
		coordinates = f.adjustAutoFilterHelper(dir, coordinates, num, offset)
		x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
		if y2-y1 < 1 || x2-x1 < 0 {
			ws.TableParts.TableParts = append(ws.TableParts.TableParts[:idx], ws.TableParts.TableParts[idx+1:]...)
			ws.TableParts.Count = len(ws.TableParts.TableParts)
			idx--
			continue
		}
		t.Ref, _ = coordinatesToRangeRef([]int{x1, y1, x2, y2})
		if t.AutoFilter != nil {
			t.AutoFilter.Ref = t.Ref
		}
		_ = f.setTableColumns(sheet, true, x1, y1, x2, &t)
		// Currently doesn't support query table
		t.TableType, t.TotalsRowCount, t.ConnectionID = "", 0, 0
		table, _ := xml.Marshal(t)
		f.saveFileList(tableXML, table)
	}
	return nil
}

// adjustAutoFilter provides a function to update the auto filter when
// inserting or deleting rows or columns.
func (f *File) adjustAutoFilter(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	if ws.AutoFilter == nil {
		return nil
	}

	coordinates, err := rangeRefToCoordinates(ws.AutoFilter.Ref)
	if err != nil {
		return err
	}
	x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]

	if (dir == rows && y1 == num && offset < 0) || (dir == columns && x1 == num && x2 == num) {
		ws.AutoFilter = nil
		for rowIdx := range ws.SheetData.Row {
			rowData := &ws.SheetData.Row[rowIdx]
			if rowData.R > y1 && rowData.R <= y2 {
				rowData.Hidden = false
			}
		}
		return err
	}

	coordinates = f.adjustAutoFilterHelper(dir, coordinates, num, offset)
	x1, y1, x2, y2 = coordinates[0], coordinates[1], coordinates[2], coordinates[3]

	ws.AutoFilter.Ref, err = coordinatesToRangeRef([]int{x1, y1, x2, y2})
	return err
}

// adjustAutoFilterHelper provides a function for adjusting auto filter to
// compare and calculate cell reference by the giving adjusting direction,
// operation reference and offset.
func (f *File) adjustAutoFilterHelper(dir adjustDirection, coordinates []int, num, offset int) []int {
	if dir == rows {
		if coordinates[1] >= num {
			coordinates[1] += offset
		}
		if coordinates[3] >= num {
			coordinates[3] += offset
		}
		return coordinates
	}
	if coordinates[0] >= num {
		coordinates[0] += offset
	}
	if coordinates[2] >= num {
		coordinates[2] += offset
	}
	return coordinates
}

// adjustMergeCells provides a function to update merged cells when inserting
// or deleting rows or columns.
func (f *File) adjustMergeCells(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	if ws.MergeCells == nil {
		return nil
	}

	for i := 0; i < len(ws.MergeCells.Cells); i++ {
		mergedCells := ws.MergeCells.Cells[i]
		mergedCellsRef := mergedCells.Ref
		if !strings.Contains(mergedCellsRef, ":") {
			mergedCellsRef += ":" + mergedCellsRef
		}
		coordinates, err := rangeRefToCoordinates(mergedCellsRef)
		if err != nil {
			return err
		}
		x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
		if dir == rows {
			if y1 == num && y2 == num && offset < 0 {
				f.deleteMergeCell(ws, i)
				i--
				continue
			}

			y1, y2 = f.adjustMergeCellsHelper(y1, y2, num, offset)
		} else {
			if x1 == num && x2 == num && offset < 0 {
				f.deleteMergeCell(ws, i)
				i--
				continue
			}

			x1, x2 = f.adjustMergeCellsHelper(x1, x2, num, offset)
		}
		if x1 == x2 && y1 == y2 {
			f.deleteMergeCell(ws, i)
			i--
			continue
		}
		mergedCells.rect = []int{x1, y1, x2, y2}
		if mergedCells.Ref, err = coordinatesToRangeRef([]int{x1, y1, x2, y2}); err != nil {
			return err
		}
	}
	return nil
}

// adjustMergeCellsHelper provides a function for adjusting merge cells to
// compare and calculate cell reference by the given pivot, operation reference
// and offset.
func (f *File) adjustMergeCellsHelper(p1, p2, num, offset int) (int, int) {
	if p2 < p1 {
		p1, p2 = p2, p1
	}

	if offset >= 0 {
		if num <= p1 {
			p1 += offset
			p2 += offset
		} else if num <= p2 {
			p2 += offset
		}
		return p1, p2
	}
	if num < p1 || (num == p1 && num == p2) {
		p1 += offset
		p2 += offset
	} else if num <= p2 {
		p2 += offset
	}
	return p1, p2
}

// deleteMergeCell provides a function to delete merged cell by given index.
func (f *File) deleteMergeCell(ws *xlsxWorksheet, idx int) {
	if idx < 0 {
		return
	}
	if len(ws.MergeCells.Cells) > idx {
		ws.MergeCells.Cells = append(ws.MergeCells.Cells[:idx], ws.MergeCells.Cells[idx+1:]...)
		ws.MergeCells.Count = len(ws.MergeCells.Cells)
	}
}

// adjustCellName returns updated cell name by giving column/row number and
// offset on inserting or deleting rows or columns.
func adjustCellName(cell string, dir adjustDirection, c, r, offset int) (string, error) {
	if dir == rows {
		if rn := r + offset; rn > 0 {
			return CoordinatesToCellName(c, rn)
		}
	}
	return CoordinatesToCellName(c+offset, r)
}

// adjustCalcChain provides a function to update the calculation chain when
// inserting or deleting rows or columns.
func (f *File) adjustCalcChain(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	if f.CalcChain == nil {
		return nil
	}
	// If sheet ID is omitted, it is assumed to be the same as the i value of
	// the previous cell.
	var prevSheetID int
	for i := 0; f.CalcChain != nil && i < len(f.CalcChain.C); i++ {
		c := f.CalcChain.C[i]
		if c.I == 0 {
			c.I = prevSheetID
		}
		prevSheetID = c.I
		if c.I != sheetID {
			continue
		}
		colNum, rowNum, err := CellNameToCoordinates(c.R)
		if err != nil {
			return err
		}
		if dir == rows && num <= rowNum {
			if num == rowNum && offset == -1 {
				_ = f.deleteCalcChain(c.I, c.R)
				i--
				continue
			}
			f.CalcChain.C[i].R, _ = adjustCellName(c.R, dir, colNum, rowNum, offset)
		}
		if dir == columns && num <= colNum {
			if num == colNum && offset == -1 {
				_ = f.deleteCalcChain(c.I, c.R)
				i--
				continue
			}
			f.CalcChain.C[i].R, _ = adjustCellName(c.R, dir, colNum, rowNum, offset)
		}
	}
	return nil
}

// adjustVolatileDepsTopic updates the volatile dependencies topic when
// inserting or deleting rows or columns.
func (vt *xlsxVolTypes) adjustVolatileDepsTopic(cell string, dir adjustDirection, indexes []int) (int, error) {
	num, offset, i1, i2, i3, i4 := indexes[0], indexes[1], indexes[2], indexes[3], indexes[4], indexes[5]
	colNum, rowNum, err := CellNameToCoordinates(cell)
	if err != nil {
		return i4, err
	}
	if dir == rows && num <= rowNum {
		if num == rowNum && offset == -1 {
			vt.deleteVolTopicRef(i1, i2, i3, i4)
			i4--
			return i4, err
		}
		vt.VolType[i1].Main[i2].Tp[i3].Tr[i4].R, _ = adjustCellName(cell, dir, colNum, rowNum, offset)
	}
	if dir == columns && num <= colNum {
		if num == colNum && offset == -1 {
			vt.deleteVolTopicRef(i1, i2, i3, i4)
			i4--
			return i4, err
		}
		if name, _ := adjustCellName(cell, dir, colNum, rowNum, offset); name != "" {
			vt.VolType[i1].Main[i2].Tp[i3].Tr[i4].R, _ = adjustCellName(cell, dir, colNum, rowNum, offset)
		}
	}
	return i4, err
}

// adjustVolatileDeps updates the volatile dependencies when inserting or
// deleting rows or columns.
func (f *File) adjustVolatileDeps(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	volTypes, err := f.volatileDepsReader()
	if err != nil || volTypes == nil {
		return err
	}
	for i1 := 0; i1 < len(volTypes.VolType); i1++ {
		for i2 := 0; i2 < len(volTypes.VolType[i1].Main); i2++ {
			for i3 := 0; i3 < len(volTypes.VolType[i1].Main[i2].Tp); i3++ {
				for i4 := 0; i4 < len(volTypes.VolType[i1].Main[i2].Tp[i3].Tr); i4++ {
					ref := volTypes.VolType[i1].Main[i2].Tp[i3].Tr[i4]
					if ref.S != sheetID {
						continue
					}
					if i4, err = volTypes.adjustVolatileDepsTopic(ref.R, dir, []int{num, offset, i1, i2, i3, i4}); err != nil {
						return err
					}
				}
			}
		}
	}
	return nil
}

// adjustConditionalFormats updates the cell reference of the worksheet
// conditional formatting when inserting or deleting rows or columns.
func (f *File) adjustConditionalFormats(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	for i := 0; i < len(ws.ConditionalFormatting); i++ {
		cf := ws.ConditionalFormatting[i]
		if cf == nil {
			continue
		}
		ref, err := f.adjustCellRef(cf.SQRef, dir, num, offset)
		if err != nil {
			return err
		}
		if ref == "" {
			ws.ConditionalFormatting = append(ws.ConditionalFormatting[:i],
				ws.ConditionalFormatting[i+1:]...)
			i--
			continue
		}
		ws.ConditionalFormatting[i].SQRef = ref
	}
	return nil
}

// adjustDataValidations updates the range of data validations for the worksheet
// when inserting or deleting rows or columns.
func (f *File) adjustDataValidations(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset, sheetID int) error {
	for _, sheetN := range f.GetSheetList() {
		worksheet, err := f.workSheetReader(sheetN)
		if err != nil {
			if err.Error() == newNotWorksheetError(sheetN).Error() {
				continue
			}
			return err
		}
		if worksheet.DataValidations == nil {
			continue
		}
		for i := 0; i < len(worksheet.DataValidations.DataValidation); i++ {
			dv := worksheet.DataValidations.DataValidation[i]
			if dv == nil {
				continue
			}
			if sheet == sheetN {
				ref, err := f.adjustCellRef(dv.Sqref, dir, num, offset)
				if err != nil {
					return err
				}
				if ref == "" {
					worksheet.DataValidations.DataValidation = append(worksheet.DataValidations.DataValidation[:i],
						worksheet.DataValidations.DataValidation[i+1:]...)
					i--
					continue
				}
				worksheet.DataValidations.DataValidation[i].Sqref = ref
			}
			if worksheet.DataValidations.DataValidation[i].Formula1.isFormula() {
				formula := formulaUnescaper.Replace(worksheet.DataValidations.DataValidation[i].Formula1.Content)
				if formula, err = f.adjustFormulaRef(sheet, sheetN, formula, false, dir, num, offset); err != nil {
					return err
				}
				worksheet.DataValidations.DataValidation[i].Formula1 = &xlsxInnerXML{Content: formulaEscaper.Replace(formula)}
			}
			if worksheet.DataValidations.DataValidation[i].Formula2.isFormula() {
				formula := formulaUnescaper.Replace(worksheet.DataValidations.DataValidation[i].Formula2.Content)
				if formula, err = f.adjustFormulaRef(sheet, sheetN, formula, false, dir, num, offset); err != nil {
					return err
				}
				worksheet.DataValidations.DataValidation[i].Formula2 = &xlsxInnerXML{Content: formulaEscaper.Replace(formula)}
			}
		}
		if worksheet.DataValidations.Count = len(worksheet.DataValidations.DataValidation); worksheet.DataValidations.Count == 0 {
			worksheet.DataValidations = nil
		}
	}
	return nil
}

// adjustDrawings updates the starting anchor of the two cell anchor pictures
// and charts object when inserting or deleting rows or columns.
func (from *xlsxFrom) adjustDrawings(dir adjustDirection, num, offset int, editAs string) (bool, error) {
	var ok bool
	if dir == columns && from.Col+1 >= num && from.Col+offset >= 0 {
		if from.Col+offset >= MaxColumns {
			return false, ErrColumnNumber
		}
		from.Col += offset
		ok = editAs == "oneCell"
	}
	if dir == rows && from.Row+1 >= num && from.Row+offset >= 0 {
		if from.Row+offset >= TotalRows {
			return false, ErrMaxRows
		}
		from.Row += offset
		ok = editAs == "oneCell"
	}
	return ok, nil
}

// adjustDrawings updates the ending anchor of the two cell anchor pictures
// and charts object when inserting or deleting rows or columns.
func (to *xlsxTo) adjustDrawings(dir adjustDirection, num, offset int, ok bool) error {
	if dir == columns && to.Col+1 >= num && to.Col+offset >= 0 && ok {
		if to.Col+offset >= MaxColumns {
			return ErrColumnNumber
		}
		to.Col += offset
	}
	if dir == rows && to.Row+1 >= num && to.Row+offset >= 0 && ok {
		if to.Row+offset >= TotalRows {
			return ErrMaxRows
		}
		to.Row += offset
	}
	return nil
}

// adjustDrawings updates the two cell anchor pictures and charts object when
// inserting or deleting rows or columns.
func (a *xdrCellAnchor) adjustDrawings(dir adjustDirection, num, offset int) error {
	editAs := a.EditAs
	if (a.From == nil && (a.To == nil || a.Ext == nil)) || editAs == "absolute" {
		return nil
	}
	ok, err := a.From.adjustDrawings(dir, num, offset, editAs)
	if err != nil {
		return err
	}
	if a.To != nil {
		return a.To.adjustDrawings(dir, num, offset, ok || editAs == "")
	}
	return err
}

// adjustDrawings updates the existing two cell anchor pictures and charts
// object when inserting or deleting rows or columns.
func (a *xlsxCellAnchorPos) adjustDrawings(dir adjustDirection, num, offset int, editAs string) error {
	if (a.From == nil && (a.To == nil || a.Ext == nil)) || editAs == "absolute" {
		return nil
	}
	ok, err := a.From.adjustDrawings(dir, num, offset, editAs)
	if err != nil {
		return err
	}
	if a.To != nil {
		return a.To.adjustDrawings(dir, num, offset, ok || editAs == "")
	}
	return err
}

// adjustDrawings updates the pictures and charts object when inserting or
// deleting rows or columns.
func (f *File) adjustDrawings(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset int) error {
	if ws.Drawing == nil {
		return nil
	}
	target := f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID)
	drawingXML := strings.TrimPrefix(strings.ReplaceAll(target, "..", "xl"), "/")
	var (
		err  error
		wsDr *xlsxWsDr
	)
	if wsDr, _, err = f.drawingParser(drawingXML); err != nil {
		return err
	}
	anchorCb := func(a *xdrCellAnchor) error {
		if a.GraphicFrame == "" {
			return a.adjustDrawings(dir, num, offset)
		}
		deCellAnchor := decodeCellAnchor{}
		deCellAnchorPos := decodeCellAnchorPos{}
		_ = f.xmlNewDecoder(strings.NewReader("<decodeCellAnchor>" + a.GraphicFrame + "</decodeCellAnchor>")).Decode(&deCellAnchor)
		_ = f.xmlNewDecoder(strings.NewReader("<decodeCellAnchorPos>" + a.GraphicFrame + "</decodeCellAnchorPos>")).Decode(&deCellAnchorPos)
		xlsxCellAnchorPos := xlsxCellAnchorPos(deCellAnchorPos)
		for i := 0; i < len(xlsxCellAnchorPos.AlternateContent); i++ {
			xlsxCellAnchorPos.AlternateContent[i].XMLNSMC = SourceRelationshipCompatibility.Value
		}
		if deCellAnchor.From != nil {
			xlsxCellAnchorPos.From = &xlsxFrom{
				Col: deCellAnchor.From.Col, ColOff: deCellAnchor.From.ColOff,
				Row: deCellAnchor.From.Row, RowOff: deCellAnchor.From.RowOff,
			}
		}
		if deCellAnchor.To != nil {
			xlsxCellAnchorPos.To = &xlsxTo{
				Col: deCellAnchor.To.Col, ColOff: deCellAnchor.To.ColOff,
				Row: deCellAnchor.To.Row, RowOff: deCellAnchor.To.RowOff,
			}
		}
		if err = xlsxCellAnchorPos.adjustDrawings(dir, num, offset, a.EditAs); err != nil {
			return err
		}
		cellAnchor, _ := xml.Marshal(xlsxCellAnchorPos)
		a.GraphicFrame = strings.TrimSuffix(strings.TrimPrefix(string(cellAnchor), "<xlsxCellAnchorPos>"), "</xlsxCellAnchorPos>")
		return err
	}
	for _, anchor := range wsDr.TwoCellAnchor {
		if err = anchorCb(anchor); err != nil {
			return err
		}
	}
	for _, anchor := range wsDr.OneCellAnchor {
		if err = anchorCb(anchor); err != nil {
			return err
		}
	}
	return nil
}

// adjustDefinedNames updates the cell reference of the defined names when
// inserting or deleting rows or columns.
func (f *File) adjustDefinedNames(sheet string, dir adjustDirection, num, offset int) error {
	wb, err := f.workbookReader()
	if err != nil {
		return err
	}
	if wb.DefinedNames != nil {
		for i := 0; i < len(wb.DefinedNames.DefinedName); i++ {
			data := wb.DefinedNames.DefinedName[i].Data
			if data, err = f.adjustFormulaRef(sheet, "", data, true, dir, num, offset); err == nil {
				wb.DefinedNames.DefinedName[i].Data = data
			}
		}
	}
	return nil
}


================================================
FILE: adjust_test.go
================================================
package excelize

import (
	"encoding/xml"
	"fmt"
	"path/filepath"
	"strings"
	"testing"

	_ "image/jpeg"

	"github.com/stretchr/testify/assert"
)

func TestAdjustMergeCells(t *testing.T) {
	f := NewFile()
	// Test adjustAutoFilter with illegal cell reference
	assert.Equal(t, f.adjustMergeCells(&xlsxWorksheet{
		MergeCells: &xlsxMergeCells{
			Cells: []*xlsxMergeCell{
				{
					Ref: "A:B1",
				},
			},
		},
	}, "Sheet1", rows, 0, 0, 1), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
	assert.Equal(t, f.adjustMergeCells(&xlsxWorksheet{
		MergeCells: &xlsxMergeCells{
			Cells: []*xlsxMergeCell{
				{
					Ref: "A1:B",
				},
			},
		},
	}, "Sheet1", rows, 0, 0, 1), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")))
	assert.NoError(t, f.adjustMergeCells(&xlsxWorksheet{
		MergeCells: &xlsxMergeCells{
			Cells: []*xlsxMergeCell{
				{
					Ref: "A1:B1",
				},
			},
		},
	}, "Sheet1", rows, 1, -1, 1))
	assert.NoError(t, f.adjustMergeCells(&xlsxWorksheet{
		MergeCells: &xlsxMergeCells{
			Cells: []*xlsxMergeCell{
				{
					Ref: "A1:A2",
				},
			},
		},
	}, "Sheet1", columns, 1, -1, 1))
	assert.NoError(t, f.adjustMergeCells(&xlsxWorksheet{
		MergeCells: &xlsxMergeCells{
			Cells: []*xlsxMergeCell{
				{
					Ref: "A2",
				},
			},
		},
	}, "Sheet1", columns, 1, -1, 1))

	// Test adjust merge cells
	var cases []struct {
		label      string
		ws         *xlsxWorksheet
		dir        adjustDirection
		num        int
		offset     int
		expect     string
		expectRect []int
	}

	// Test adjust merged cell when insert rows and columns
	cases = []struct {
		label      string
		ws         *xlsxWorksheet
		dir        adjustDirection
		num        int
		offset     int
		expect     string
		expectRect []int
	}{
		{
			label: "insert row on ref",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        rows,
			num:        2,
			offset:     1,
			expect:     "A3:B4",
			expectRect: []int{1, 3, 2, 4},
		},
		{
			label: "insert row on bottom of ref",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        rows,
			num:        3,
			offset:     1,
			expect:     "A2:B4",
			expectRect: []int{1, 2, 2, 4},
		},
		{
			label: "insert column on the left",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        columns,
			num:        1,
			offset:     1,
			expect:     "B2:C3",
			expectRect: []int{2, 2, 3, 3},
		},
	}
	for _, c := range cases {
		assert.NoError(t, f.adjustMergeCells(c.ws, "Sheet1", c.dir, c.num, 1, 1))
		assert.Equal(t, c.expect, c.ws.MergeCells.Cells[0].Ref, c.label)
		assert.Equal(t, c.expectRect, c.ws.MergeCells.Cells[0].rect, c.label)
	}

	// Test adjust merged cells when delete rows and columns
	cases = []struct {
		label      string
		ws         *xlsxWorksheet
		dir        adjustDirection
		num        int
		offset     int
		expect     string
		expectRect []int
	}{
		{
			label: "delete row on top of ref",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        rows,
			num:        2,
			offset:     -1,
			expect:     "A2:B2",
			expectRect: []int{1, 2, 2, 2},
		},
		{
			label: "delete row on bottom of ref",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        rows,
			num:        3,
			offset:     -1,
			expect:     "A2:B2",
			expectRect: []int{1, 2, 2, 2},
		},
		{
			label: "delete column on the ref left",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        columns,
			num:        1,
			offset:     -1,
			expect:     "A2:A3",
			expectRect: []int{1, 2, 1, 3},
		},
		{
			label: "delete column on the ref right",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A2:B3",
							rect: []int{1, 2, 2, 3},
						},
					},
				},
			},
			dir:        columns,
			num:        2,
			offset:     -1,
			expect:     "A2:A3",
			expectRect: []int{1, 2, 1, 3},
		},
	}
	for _, c := range cases {
		assert.NoError(t, f.adjustMergeCells(c.ws, "Sheet1", c.dir, c.num, -1, 1))
		assert.Equal(t, c.expect, c.ws.MergeCells.Cells[0].Ref, c.label)
	}

	// Test delete one row or column
	cases = []struct {
		label      string
		ws         *xlsxWorksheet
		dir        adjustDirection
		num        int
		offset     int
		expect     string
		expectRect []int
	}{
		{
			label: "delete one row ref",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A1:B1",
							rect: []int{1, 1, 2, 1},
						},
					},
				},
			},
			dir:    rows,
			num:    1,
			offset: -1,
		},
		{
			label: "delete one column ref",
			ws: &xlsxWorksheet{
				MergeCells: &xlsxMergeCells{
					Cells: []*xlsxMergeCell{
						{
							Ref:  "A1:A2",
							rect: []int{1, 1, 1, 2},
						},
					},
				},
			},
			dir:    columns,
			num:    1,
			offset: -1,
		},
	}
	for _, c := range cases {
		assert.NoError(t, f.adjustMergeCells(c.ws, "Sheet1", c.dir, c.num, -1, 1))
		assert.Len(t, c.ws.MergeCells.Cells, 0, c.label)
	}

	f = NewFile()
	p1, p2 := f.adjustMergeCellsHelper(2, 1, 0, 0)
	assert.Equal(t, 1, p1)
	assert.Equal(t, 2, p2)
	f.deleteMergeCell(nil, -1)
}

func TestAdjustAutoFilter(t *testing.T) {
	f := NewFile()
	assert.NoError(t, f.adjustAutoFilter(&xlsxWorksheet{
		SheetData: xlsxSheetData{
			Row: []xlsxRow{{Hidden: true, R: 2}},
		},
		AutoFilter: &xlsxAutoFilter{
			Ref: "A1:A3",
		},
	}, "Sheet1", rows, 1, -1, 1))
	// Test adjustAutoFilter with illegal cell reference
	assert.Equal(t, f.adjustAutoFilter(&xlsxWorksheet{
		AutoFilter: &xlsxAutoFilter{
			Ref: "A:B1",
		},
	}, "Sheet1", rows, 0, 0, 1), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
	assert.Equal(t, f.adjustAutoFilter(&xlsxWorksheet{
		AutoFilter: &xlsxAutoFilter{
			Ref: "A1:B",
		},
	}, "Sheet1", rows, 0, 0, 1), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")))
}

func TestAdjustTable(t *testing.T) {
	f, sheetName := NewFile(), "Sheet1"
	for idx, reference := range []string{"B2:C3", "E3:F5", "H5:H8", "J5:K9"} {
		assert.NoError(t, f.AddTable(sheetName, &Table{
			Range:             reference,
			Name:              fmt.Sprintf("table%d", idx),
			StyleName:         "TableStyleMedium2",
			ShowFirstColumn:   true,
			ShowLastColumn:    true,
			ShowRowStripes:    boolPtr(false),
			ShowColumnStripes: true,
		}))
	}
	assert.NoError(t, f.RemoveRow(sheetName, 2))
	assert.NoError(t, f.RemoveRow(sheetName, 3))
	assert.NoError(t, f.RemoveRow(sheetName, 3))
	assert.NoError(t, f.RemoveCol(sheetName, "H"))
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustTable.xlsx")))

	f = NewFile()
	assert.NoError(t, f.AddTable(sheetName, &Table{Range: "A1:D5"}))
	// Test adjust table with non-table part
	f.Pkg.Delete("xl/tables/table1.xml")
	assert.NoError(t, f.RemoveRow(sheetName, 1))
	// Test adjust table with unsupported charset
	f.Pkg.Store("xl/tables/table1.xml", MacintoshCyrillicCharset)
	assert.EqualError(t, f.RemoveRow(sheetName, 1), "XML syntax error on line 1: invalid UTF-8")
	// Test adjust table with invalid table range reference
	f.Pkg.Store("xl/tables/table1.xml", []byte(`<table ref="-" />`))
	assert.Equal(t, ErrParameterInvalid, f.RemoveRow(sheetName, 1))
}

func TestAdjustHelper(t *testing.T) {
	f := NewFile()
	_, err := f.NewSheet("Sheet2")
	assert.NoError(t, err)
	f.Sheet.Store("xl/worksheets/sheet1.xml", &xlsxWorksheet{
		MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:B1"}}},
	})
	f.Sheet.Store("xl/worksheets/sheet2.xml", &xlsxWorksheet{
		AutoFilter: &xlsxAutoFilter{Ref: "A1:B"},
	})
	// Test adjustHelper with illegal cell reference
	assert.Equal(t, f.adjustHelper("Sheet1", rows, 0, 0), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
	assert.Equal(t, f.adjustHelper("Sheet2", rows, 0, 0), newCellNameToCoordinatesError("B", newInvalidCellNameError("B")))
	// Test adjustHelper on not exists worksheet
	assert.EqualError(t, f.adjustHelper("SheetN", rows, 0, 0), "sheet SheetN does not exist")
}

func TestAdjustCalcChain(t *testing.T) {
	f := NewFile()
	f.CalcChain = &xlsxCalcChain{
		C: []xlsxCalcChainC{{R: "B2", I: 2}, {R: "B2", I: 1}, {R: "A1", I: 1}},
	}
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))

	f.CalcChain = &xlsxCalcChain{
		C: []xlsxCalcChainC{{R: "B2", I: 1}, {R: "B3"}, {R: "A1"}},
	}
	assert.NoError(t, f.RemoveRow("Sheet1", 3))
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))

	f.CalcChain = &xlsxCalcChain{C: []xlsxCalcChainC{{R: "B2", I: 2}, {R: "B2", I: 1}}}
	f.CalcChain.C[1].R = "invalid coordinates"
	assert.Equal(t, f.InsertCols("Sheet1", "A", 1), newCellNameToCoordinatesError("invalid coordinates", newInvalidCellNameError("invalid coordinates")))
	f.CalcChain = nil
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
}

func TestAdjustCols(t *testing.T) {
	sheetName := "Sheet1"
	preset := func() (*File, error) {
		f := NewFile()
		if err := f.SetColWidth(sheetName, "J", "T", 5); err != nil {
			return f, err
		}
		if err := f.SetSheetRow(sheetName, "J1", &[]string{"J1", "K1", "L1", "M1", "N1", "O1", "P1", "Q1", "R1", "S1", "T1"}); err != nil {
			return f, err
		}
		return f, nil
	}
	baseTbl := []string{"B", "J", "O", "O", "O", "U", "V"}
	insertTbl := []int{2, 2, 2, 5, 6, 2, 2}
	expectedTbl := []map[string]float64{
		{"J": defaultColWidth, "K": defaultColWidth, "U": 5, "V": 5, "W": defaultColWidth},
		{"J": defaultColWidth, "K": defaultColWidth, "U": 5, "V": 5, "W": defaultColWidth},
		{"O": 5, "P": 5, "U": 5, "V": 5, "W": defaultColWidth},
		{"O": 5, "S": 5, "X": 5, "Y": 5, "Z": defaultColWidth},
		{"O": 5, "S": 5, "Y": 5, "X": 5, "AA": defaultColWidth},
		{"U": 5, "V": 5, "W": defaultColWidth},
		{"U": defaultColWidth, "V": defaultColWidth, "W": defaultColWidth},
	}
	for idx, columnName := range baseTbl {
		f, err := preset()
		assert.NoError(t, err)
		assert.NoError(t, f.InsertCols(sheetName, columnName, insertTbl[idx]))
		for column, expected := range expectedTbl[idx] {
			width, err := f.GetColWidth(sheetName, column)
			assert.NoError(t, err)
			assert.Equal(t, expected, width, column)
		}
		assert.NoError(t, f.Close())
	}

	baseTbl = []string{"B", "J", "O", "T"}
	expectedTbl = []map[string]float64{
		{"H": defaultColWidth, "I": 5, "S": 5, "T": defaultColWidth},
		{"I": defaultColWidth, "J": 5, "S": 5, "T": defaultColWidth},
		{"I": defaultColWidth, "O": 5, "S": 5, "T": defaultColWidth},
		{"R": 5, "S": 5, "T": defaultColWidth, "U": defaultColWidth},
	}
	for idx, columnName := range baseTbl {
		f, err := preset()
		assert.NoError(t, err)
		assert.NoError(t, f.RemoveCol(sheetName, columnName))
		for column, expected := range expectedTbl[idx] {
			width, err := f.GetColWidth(sheetName, column)
			assert.NoError(t, err)
			assert.Equal(t, expected, width, column)
		}
		assert.NoError(t, f.Close())
	}

	f, err := preset()
	assert.NoError(t, err)
	assert.NoError(t, f.SetColWidth(sheetName, "I", "I", 8))
	for i := 0; i <= 12; i++ {
		assert.NoError(t, f.RemoveCol(sheetName, "I"))
	}
	for c := 9; c <= 21; c++ {
		columnName, err := ColumnNumberToName(c)
		assert.NoError(t, err)
		width, err := f.GetColWidth(sheetName, columnName)
		assert.NoError(t, err)
		assert.Equal(t, defaultColWidth, width, columnName)
	}

	ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
	assert.True(t, ok)
	ws.(*xlsxWorksheet).Cols = nil
	assert.NoError(t, f.RemoveCol(sheetName, "A"))

	assert.NoError(t, f.Close())

	f = NewFile()
	assert.NoError(t, f.SetColWidth("Sheet1", "XFB", "XFC", 12))
	assert.NoError(t, f.InsertCols("Sheet1", "A", 2))
	ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
	assert.True(t, ok)
	assert.Equal(t, MaxColumns, ws.(*xlsxWorksheet).Cols.Col[0].Min)
	assert.Equal(t, MaxColumns, ws.(*xlsxWorksheet).Cols.Col[0].Max)

	assert.NoError(t, f.InsertCols("Sheet1", "A", 2))
	assert.Nil(t, ws.(*xlsxWorksheet).Cols)

	f = NewFile()
	assert.NoError(t, f.SetCellFormula("Sheet1", "A2", "(1-0.5)/2"))
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	formula, err := f.GetCellFormula("Sheet1", "B2")
	assert.NoError(t, err)
	assert.Equal(t, "(1-0.5)/2", formula)
	assert.NoError(t, f.Close())
}

func TestAdjustColDimensions(t *testing.T) {
	f := NewFile()
	ws, err := f.workSheetReader("Sheet1")
	assert.NoError(t, err)
	assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
	assert.Equal(t, ErrColumnNumber, f.adjustColDimensions("Sheet1", ws, 1, MaxColumns))

	_, err = f.NewSheet("Sheet2")
	assert.NoError(t, err)
	f.Sheet.Delete("xl/worksheets/sheet2.xml")
	f.Pkg.Store("xl/worksheets/sheet2.xml", MacintoshCyrillicCharset)
	assert.EqualError(t, f.adjustColDimensions("Sheet2", ws, 2, 1), "XML syntax error on line 1: invalid UTF-8")
}

func TestAdjustRowDimensions(t *testing.T) {
	f := NewFile()
	ws, err := f.workSheetReader("Sheet1")
	assert.NoError(t, err)
	assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
	assert.Equal(t, ErrMaxRows, f.adjustRowDimensions("Sheet1", ws, 1, TotalRows))

	_, err = f.NewSheet("Sheet2")
	assert.NoError(t, err)
	f.Sheet.Delete("xl/worksheets/sheet2.xml")
	f.Pkg.Store("xl/worksheets/sheet2.xml", MacintoshCyrillicCharset)
	assert.EqualError(t, f.adjustRowDimensions("Sheet1", ws, 2, 1), "XML syntax error on line 1: invalid UTF-8")

	f = NewFile()
	_, err = f.NewSheet("Sheet2")
	assert.NoError(t, err)
	ws, err = f.workSheetReader("Sheet1")
	assert.NoError(t, err)
	assert.NoError(t, f.SetCellFormula("Sheet1", "B2", fmt.Sprintf("Sheet2!A%d", TotalRows)))
	assert.Equal(t, ErrMaxRows, f.adjustRowDimensions("Sheet2", ws, 1, TotalRows))
}

func TestAdjustHyperlinks(t *testing.T) {
	f := NewFile()
	ws, err := f.workSheetReader("Sheet1")
	assert.NoError(t, err)
	assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
	f.adjustHyperlinks(ws, "Sheet1", rows, 3, -1)

	// Test adjust hyperlinks location with positive offset
	assert.NoError(t, f.SetCellHyperLink("Sheet1", "F5", "Sheet1!A1", "Location"))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	link, target, err := f.GetCellHyperLink("Sheet1", "F6")
	assert.NoError(t, err)
	assert.True(t, link)
	assert.Equal(t, target, "Sheet1!A1")

	// Test adjust hyperlinks location with negative offset
	assert.NoError(t, f.RemoveRow("Sheet1", 1))
	link, target, err = f.GetCellHyperLink("Sheet1", "F5")
	assert.NoError(t, err)
	assert.True(t, link)
	assert.Equal(t, target, "Sheet1!A1")

	// Test adjust hyperlinks location on remove row
	assert.NoError(t, f.RemoveRow("Sheet1", 5))
	link, target, err = f.GetCellHyperLink("Sheet1", "F5")
	assert.NoError(t, err)
	assert.False(t, link)
	assert.Empty(t, target)

	// Test adjust hyperlinks location on remove column
	assert.NoError(t, f.SetCellHyperLink("Sheet1", "F5", "Sheet1!A1", "Location"))
	assert.NoError(t, f.RemoveCol("Sheet1", "F"))
	link, target, err = f.GetCellHyperLink("Sheet1", "F5")
	assert.NoError(t, err)
	assert.False(t, link)
	assert.Empty(t, target)

	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustHyperlinks.xlsx")))
	assert.NoError(t, f.Close())
}

func TestAdjustFormula(t *testing.T) {
	f := NewFile()
	formulaType, ref := STCellFormulaTypeShared, "C1:C5"
	assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "A1+B1", FormulaOpts{Ref: &ref, Type: &formulaType}))
	assert.NoError(t, f.DuplicateRowTo("Sheet1", 1, 10))
	assert.NoError(t, f.InsertCols("Sheet1", "B", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	for cell, expected := range map[string]string{"D2": "A2+C2", "D3": "A3+C3", "D11": "A11+C11"} {
		formula, err := f.GetCellFormula("Sheet1", cell)
		assert.NoError(t, err)
		assert.Equal(t, expected, formula)
	}
	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustFormula.xlsx")))
	assert.NoError(t, f.Close())

	assert.NoError(t, f.adjustFormula("Sheet1", "Sheet1", &xlsxC{}, rows, 0, 0, false))
	assert.Equal(t, newCellNameToCoordinatesError("-", newInvalidCellNameError("-")), f.adjustFormula("Sheet1", "Sheet1", &xlsxC{F: &xlsxF{Ref: "-"}}, rows, 0, 0, false))
	assert.Equal(t, ErrColumnNumber, f.adjustFormula("Sheet1", "Sheet1", &xlsxC{F: &xlsxF{Ref: "XFD1:XFD1"}}, columns, 0, 1, false))

	_, err := f.adjustFormulaRef("Sheet1", "Sheet1", "XFE1", false, columns, 0, 1)
	assert.Equal(t, ErrColumnNumber, err)
	_, err = f.adjustFormulaRef("Sheet1", "Sheet1", "XFD1", false, columns, 0, 1)
	assert.Equal(t, ErrColumnNumber, err)

	f = NewFile()
	assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "XFD1"))
	assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))

	assert.NoError(t, f.SetCellFormula("Sheet1", "B2", fmt.Sprintf("A%d", TotalRows)))
	assert.Equal(t, ErrMaxRows, f.InsertRows("Sheet1", 1, 1))

	f = NewFile()
	assert.NoError(t, f.SetCellFormula("Sheet1", "B3", "SUM(1048576:1:2)"))
	assert.Equal(t, ErrMaxRows, f.InsertRows("Sheet1", 1, 1))

	f = NewFile()
	assert.NoError(t, f.SetCellFormula("Sheet1", "B3", "SUM(XFD:A:B)"))
	assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))

	f = NewFile()
	assert.NoError(t, f.SetCellFormula("Sheet1", "B3", "SUM(A:B:XFD)"))
	assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))

	// Test adjust formula with defined name in formula text
	f = NewFile()
	assert.NoError(t, f.SetDefinedName(&DefinedName{
		Name:     "Amount",
		RefersTo: "Sheet1!$B$2",
	}))
	assert.NoError(t, f.SetCellFormula("Sheet1", "B2", "Amount+B3"))
	assert.NoError(t, f.RemoveRow("Sheet1", 1))
	formula, err := f.GetCellFormula("Sheet1", "B1")
	assert.NoError(t, err)
	assert.Equal(t, "Amount+B2", formula)

	// Test adjust formula with array formula
	f = NewFile()
	formulaType, reference := STCellFormulaTypeArray, "A3:A3"
	assert.NoError(t, f.SetCellFormula("Sheet1", "A3", "A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	formula, err = f.GetCellFormula("Sheet1", "A4")
	assert.NoError(t, err)
	assert.Equal(t, "A2:A3", formula)

	// Test adjust formula on duplicate row with array formula
	f = NewFile()
	formulaType, reference = STCellFormulaTypeArray, "A3"
	assert.NoError(t, f.SetCellFormula("Sheet1", "A3", "A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	formula, err = f.GetCellFormula("Sheet1", "A4")
	assert.NoError(t, err)
	assert.Equal(t, "A2:A3", formula)

	// Test adjust formula on duplicate row with relative and absolute cell references
	f = NewFile()
	assert.NoError(t, f.SetCellFormula("Sheet1", "B10", "A$10+$A11&\" \""))
	assert.NoError(t, f.DuplicateRowTo("Sheet1", 10, 2))
	formula, err = f.GetCellFormula("Sheet1", "B2")
	assert.NoError(t, err)
	assert.Equal(t, "A$2+$A3&\" \"", formula)

	t.Run("for_cells_affected_directly", func(t *testing.T) {
		// Test insert row in middle of range with relative and absolute cell references
		f := NewFile()
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "$A1+A$2"))
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		formula, err := f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "$A1+A$3", formula)
		assert.NoError(t, f.RemoveRow("Sheet1", 2))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "$A1+A$2", formula)

		// Test insert column in middle of range
		f = NewFile()
		assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "B1+C1"))
		assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
		formula, err = f.GetCellFormula("Sheet1", "A1")
		assert.NoError(t, err)
		assert.Equal(t, "B1+D1", formula)
		assert.NoError(t, f.RemoveCol("Sheet1", "C"))
		formula, err = f.GetCellFormula("Sheet1", "A1")
		assert.NoError(t, err)
		assert.Equal(t, "B1+C1", formula)

		// Test insert row and column in a rectangular range
		f = NewFile()
		assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "D4+D5+E4+E5"))
		assert.NoError(t, f.InsertCols("Sheet1", "E", 1))
		assert.NoError(t, f.InsertRows("Sheet1", 5, 1))
		formula, err = f.GetCellFormula("Sheet1", "A1")
		assert.NoError(t, err)
		assert.Equal(t, "D4+D6+F4+F6", formula)

		// Test insert row in middle of range
		f = NewFile()
		formulaType, reference := STCellFormulaTypeArray, "B1:B1"
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "A1:A3", formula)
		assert.NoError(t, f.RemoveRow("Sheet1", 2))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "A1:A2", formula)

		// Test insert column in middle of range
		f = NewFile()
		formulaType, reference = STCellFormulaTypeArray, "A1:A1"
		assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "B1:C1", FormulaOpts{Ref: &reference, Type: &formulaType}))
		assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
		formula, err = f.GetCellFormula("Sheet1", "A1")
		assert.NoError(t, err)
		assert.Equal(t, "B1:D1", formula)
		assert.NoError(t, f.RemoveCol("Sheet1", "C"))
		formula, err = f.GetCellFormula("Sheet1", "A1")
		assert.NoError(t, err)
		assert.Equal(t, "B1:C1", formula)

		// Test insert row and column in a rectangular range
		f = NewFile()
		formulaType, reference = STCellFormulaTypeArray, "A1:A1"
		assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "D4:E5", FormulaOpts{Ref: &reference, Type: &formulaType}))
		assert.NoError(t, f.InsertCols("Sheet1", "E", 1))
		assert.NoError(t, f.InsertRows("Sheet1", 5, 1))
		formula, err = f.GetCellFormula("Sheet1", "A1")
		assert.NoError(t, err)
		assert.Equal(t, "D4:F6", formula)
	})
	t.Run("for_cells_affected_indirectly", func(t *testing.T) {
		f := NewFile()
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "A3+A4"))
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		formula, err := f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "A4+A5", formula)
		assert.NoError(t, f.RemoveRow("Sheet1", 2))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "A3+A4", formula)

		f = NewFile()
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "D3+D4"))
		assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "E3+E4", formula)
		assert.NoError(t, f.RemoveCol("Sheet1", "C"))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "D3+D4", formula)
	})
	t.Run("for_entire_cols_rows_reference", func(t *testing.T) {
		f := NewFile()
		// Test adjust formula on insert row in the middle of the range
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(A2:A3:A4,,Table1[])"))
		assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
		formula, err := f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(A2:A4:A5,,Table1[])", formula)

		// Test adjust formula on insert at the top of the range
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(A3:A5:A6,,Table1[])", formula)

		f = NewFile()
		// Test adjust formula on insert row in the middle of the range
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM('Sheet 1'!A2,A3)"))
		assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM('Sheet 1'!A2,A4)", formula)

		// Test adjust formula on insert row at the top of the range
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM('Sheet 1'!A2,A5)", formula)

		f = NewFile()
		// Test adjust formula on insert col in the middle of the range
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(C3:D3)"))
		assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(C3:E3)", formula)

		// Test adjust formula on insert at the top of the range
		assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(D3:F3)", formula)

		f = NewFile()
		// Test adjust formula on insert column in the middle of the range
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(C3,D3)"))
		assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(C3,E3)", formula)

		// Test adjust formula on insert column at the top of the range
		assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(D3,F3)", formula)

		f = NewFile()
		// Test adjust formula on insert row in the middle of the range (range of whole row)
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(2:3)"))
		assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(2:4)", formula)

		// Test adjust formula on insert row at the top of the range (range of whole row)
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(3:5)", formula)

		f = NewFile()
		// Test adjust formula on insert row in the middle of the range (range of whole column)
		assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(C:D)"))
		assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(C:E)", formula)

		// Test adjust formula on insert row at the top of the range (range of whole column)
		assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
		formula, err = f.GetCellFormula("Sheet1", "B1")
		assert.NoError(t, err)
		assert.Equal(t, "SUM(D:F)", formula)
	})
	t.Run("for_all_worksheet_cells_with_rows_insert", func(t *testing.T) {
		f := NewFile()
		_, err := f.NewSheet("Sheet2")
		assert.NoError(t, err)
		// Tests formulas referencing Sheet2 should update but those referencing the original sheet should not
		tbl := [][]string{
			{"B1", "Sheet2!A1+Sheet2!A2", "Sheet2!A1+Sheet2!A3", "Sheet2!A2+Sheet2!A4"},
			{"C1", "A1+A2", "A1+A2", "A1+A2"},
			{"D1", "Sheet2!B1:B2", "Sheet2!B1:B3", "Sheet2!B2:B4"},
			{"E1", "B1:B2", "B1:B2", "B1:B2"},
			{"F1", "SUM(Sheet2!C1:C2)", "SUM(Sheet2!C1:C3)", "SUM(Sheet2!C2:C4)"},
			{"G1", "SUM(C1:C2)", "SUM(C1:C2)", "SUM(C1:C2)"},
			{"H1", "SUM(Sheet2!D1,Sheet2!D2)", "SUM(Sheet2!D1,Sheet2!D3)", "SUM(Sheet2!D2,Sheet2!D4)"},
			{"I1", "SUM(D1,D2)", "SUM(D1,D2)", "SUM(D1,D2)"},
		}
		for _, preset := range tbl {
			assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
		}
		// Test adjust formula on insert row in the middle of the range
		assert.NoError(t, f.InsertRows("Sheet2", 2, 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[2], formula)
		}

		// Test adjust formula on insert row in the top of the range
		assert.NoError(t, f.InsertRows("Sheet2", 1, 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[3], formula)
		}
	})
	t.Run("for_all_worksheet_cells_with_cols_insert", func(t *testing.T) {
		f := NewFile()
		_, err := f.NewSheet("Sheet2")
		assert.NoError(t, err)
		tbl := [][]string{
			{"A1", "Sheet2!A1+Sheet2!B1", "Sheet2!A1+Sheet2!C1", "Sheet2!B1+Sheet2!D1"},
			{"A2", "A1+B1", "A1+B1", "A1+B1"},
			{"A3", "Sheet2!A2:B2", "Sheet2!A2:C2", "Sheet2!B2:D2"},
			{"A4", "A2:B2", "A2:B2", "A2:B2"},
			{"A5", "SUM(Sheet2!A3:B3)", "SUM(Sheet2!A3:C3)", "SUM(Sheet2!B3:D3)"},
			{"A6", "SUM(A3:B3)", "SUM(A3:B3)", "SUM(A3:B3)"},
			{"A7", "SUM(Sheet2!A4,Sheet2!B4)", "SUM(Sheet2!A4,Sheet2!C4)", "SUM(Sheet2!B4,Sheet2!D4)"},
			{"A8", "SUM(A4,B4)", "SUM(A4,B4)", "SUM(A4,B4)"},
		}
		for _, preset := range tbl {
			assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
		}
		// Test adjust formula on insert column in the middle of the range
		assert.NoError(t, f.InsertCols("Sheet2", "B", 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[2], formula)
		}
		// Test adjust formula on insert column in the top of the range
		assert.NoError(t, f.InsertCols("Sheet2", "A", 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[3], formula)
		}
	})
	t.Run("for_cross_sheet_ref_with_rows_insert)", func(t *testing.T) {
		f := NewFile()
		_, err := f.NewSheet("Sheet2")
		assert.NoError(t, err)
		_, err = f.NewSheet("Sheet3")
		assert.NoError(t, err)
		// Tests formulas referencing Sheet2 should update but those referencing
		// the original sheet or Sheet 3 should not update
		tbl := [][]string{
			{"B1", "Sheet2!A1+Sheet2!A2+Sheet1!A3+Sheet1!A4", "Sheet2!A1+Sheet2!A3+Sheet1!A3+Sheet1!A4", "Sheet2!A2+Sheet2!A4+Sheet1!A3+Sheet1!A4"},
			{"C1", "Sheet2!B1+Sheet2!B2+B3+B4", "Sheet2!B1+Sheet2!B3+B3+B4", "Sheet2!B2+Sheet2!B4+B3+B4"},
			{"D1", "Sheet2!C1+Sheet2!C2+Sheet3!A3+Sheet3!A4", "Sheet2!C1+Sheet2!C3+Sheet3!A3+Sheet3!A4", "Sheet2!C2+Sheet2!C4+Sheet3!A3+Sheet3!A4"},
			{"E1", "SUM(Sheet2!D1:D2,Sheet1!A3:A4)", "SUM(Sheet2!D1:D3,Sheet1!A3:A4)", "SUM(Sheet2!D2:D4,Sheet1!A3:A4)"},
			{"F1", "SUM(Sheet2!E1:E2,A3:A4)", "SUM(Sheet2!E1:E3,A3:A4)", "SUM(Sheet2!E2:E4,A3:A4)"},
			{"G1", "SUM(Sheet2!F1:F2,Sheet3!A3:A4)", "SUM(Sheet2!F1:F3,Sheet3!A3:A4)", "SUM(Sheet2!F2:F4,Sheet3!A3:A4)"},
		}
		for _, preset := range tbl {
			assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
		}
		// Test adjust formula on insert row in the middle of the range
		assert.NoError(t, f.InsertRows("Sheet2", 2, 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[2], formula)
		}
		// Test adjust formula on insert row in the top of the range
		assert.NoError(t, f.InsertRows("Sheet2", 1, 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[3], formula)
		}
	})
	t.Run("for_cross_sheet_ref_with_cols_insert)", func(t *testing.T) {
		f := NewFile()
		_, err := f.NewSheet("Sheet2")
		assert.NoError(t, err)
		_, err = f.NewSheet("Sheet3")
		assert.NoError(t, err)
		// Tests formulas referencing Sheet2 should update but those referencing
		// the original sheet or Sheet 3 should not update
		tbl := [][]string{
			{"A1", "Sheet2!A1+Sheet2!B1+Sheet1!C1+Sheet1!D1", "Sheet2!A1+Sheet2!C1+Sheet1!C1+Sheet1!D1", "Sheet2!B1+Sheet2!D1+Sheet1!C1+Sheet1!D1"},
			{"A2", "Sheet2!A2+Sheet2!B2+C2+D2", "Sheet2!A2+Sheet2!C2+C2+D2", "Sheet2!B2+Sheet2!D2+C2+D2"},
			{"A3", "Sheet2!A3+Sheet2!B3+Sheet3!C3+Sheet3!D3", "Sheet2!A3+Sheet2!C3+Sheet3!C3+Sheet3!D3", "Sheet2!B3+Sheet2!D3+Sheet3!C3+Sheet3!D3"},
			{"A4", "SUM(Sheet2!A4:B4,Sheet1!C4:D4)", "SUM(Sheet2!A4:C4,Sheet1!C4:D4)", "SUM(Sheet2!B4:D4,Sheet1!C4:D4)"},
			{"A5", "SUM(Sheet2!A5:B5,C5:D5)", "SUM(Sheet2!A5:C5,C5:D5)", "SUM(Sheet2!B5:D5,C5:D5)"},
			{"A6", "SUM(Sheet2!A6:B6,Sheet3!C6:D6)", "SUM(Sheet2!A6:C6,Sheet3!C6:D6)", "SUM(Sheet2!B6:D6,Sheet3!C6:D6)"},
		}
		for _, preset := range tbl {
			assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
		}
		// Test adjust formula on insert row in the middle of the range
		assert.NoError(t, f.InsertCols("Sheet2", "B", 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[2], formula)
		}
		// Test adjust formula on insert row in the top of the range
		assert.NoError(t, f.InsertCols("Sheet2", "A", 1))
		for _, preset := range tbl {
			formula, err := f.GetCellFormula("Sheet1", preset[0])
			assert.NoError(t, err)
			assert.Equal(t, preset[3], formula)
		}
	})
	t.Run("for_cross_sheet_ref_with_chart_sheet)", func(t *testing.T) {
		assert.NoError(t, f.AddChartSheet("Chart1", &Chart{Type: Line}))
		assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
		assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	})
	t.Run("for_array_formula_cell", func(t *testing.T) {
		f := NewFile()
		assert.NoError(t, f.SetSheetRow("Sheet1", "A1", &[]int{1, 2}))
		assert.NoError(t, f.SetSheetRow("Sheet1", "A2", &[]int{3, 4}))
		formulaType, ref := STCellFormulaTypeArray, "C1:C2"
		assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "A1:A2*B1:B2", FormulaOpts{Ref: &ref, Type: &formulaType}))
		assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
		assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
		result, err := f.CalcCellValue("Sheet1", "D2")
		assert.NoError(t, err)
		assert.Equal(t, "2", result)
		result, err = f.CalcCellValue("Sheet1", "D3")
		assert.NoError(t, err)
		assert.Equal(t, "12", result)

		// Test adjust array formula with invalid range reference
		formulaType, ref = STCellFormulaTypeArray, "E1:E2"
		assert.NoError(t, f.SetCellFormula("Sheet1", "E1", "XFD1:XFD1", FormulaOpts{Ref: &ref, Type: &formulaType}))
		assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))
	})
}

func TestAdjustVolatileDeps(t *testing.T) {
	f := NewFile()
	f.Pkg.Store(defaultXMLPathVolatileDeps, []byte(fmt.Sprintf(`<volTypes xmlns="%s"><volType><main><tp><tr r="C2" s="2"/><tr r="C2" s="1"/><tr r="D3" s="1"/></tp></main></volType></volTypes>`, NameSpaceSpreadSheet.Value)))
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
	assert.Equal(t, "D3", f.VolatileDeps.VolType[0].Main[0].Tp[0].Tr[1].R)
	assert.NoError(t, f.RemoveCol("Sheet1", "D"))
	assert.NoError(t, f.RemoveRow("Sheet1", 4))
	assert.Len(t, f.VolatileDeps.VolType[0].Main[0].Tp[0].Tr, 1)

	f = NewFile()
	f.Pkg.Store(defaultXMLPathVolatileDeps, MacintoshCyrillicCharset)
	assert.EqualError(t, f.InsertRows("Sheet1", 2, 1), "XML syntax error on line 1: invalid UTF-8")

	f = NewFile()
	f.Pkg.Store(defaultXMLPathVolatileDeps, []byte(fmt.Sprintf(`<volTypes xmlns="%s"><volType><main><tp><tr r="A" s="1"/></tp></main></volType></volTypes>`, NameSpaceSpreadSheet.Value)))
	assert.Equal(t, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")), f.InsertCols("Sheet1", "A", 1))
	f.volatileDepsWriter()
}

func TestAdjustConditionalFormats(t *testing.T) {
	f := NewFile()
	assert.NoError(t, f.SetSheetRow("Sheet1", "B1", &[]interface{}{1, nil, 1, 1}))
	formatID, err := f.NewConditionalStyle(&Style{Font: &Font{Color: "09600B"}, Fill: Fill{Type: "pattern", Color: []string{"C7EECF"}, Pattern: 1}})
	assert.NoError(t, err)
	format := []ConditionalFormatOptions{
		{
			Type:     "cell",
			Criteria: "greater than",
			Format:   &formatID,
			Value:    "0",
		},
	}
	for _, ref := range []string{"B1", "D1:E1"} {
		assert.NoError(t, f.SetConditionalFormat("Sheet1", ref, format))
	}
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))
	opts, err := f.GetConditionalFormats("Sheet1")
	assert.NoError(t, err)
	assert.Len(t, format, 1)
	assert.Equal(t, format, opts["C1:D1"])

	ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
	assert.True(t, ok)
	ws.(*xlsxWorksheet).ConditionalFormatting[0].SQRef = "-"
	assert.Equal(t, newCellNameToCoordinatesError("-", newInvalidCellNameError("-")), f.RemoveCol("Sheet1", "B"))

	ws.(*xlsxWorksheet).ConditionalFormatting[0] = nil
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))

	t.Run("for_remove_conditional_formats_column", func(t *testing.T) {
		f := NewFile()
		format := []ConditionalFormatOptions{{
			Type:     "data_bar",
			Criteria: "=",
			MinType:  "min",
			MaxType:  "max",
			BarColor: "#638EC6",
		}}
		assert.NoError(t, f.SetConditionalFormat("Sheet1", "D2:D3", format))
		assert.NoError(t, f.SetConditionalFormat("Sheet1", "D5", format))
		assert.NoError(t, f.RemoveCol("Sheet1", "D"))
		opts, err := f.GetConditionalFormats("Sheet1")
		assert.NoError(t, err)
		assert.Len(t, opts, 0)
	})
	t.Run("for_remove_conditional_formats_row", func(t *testing.T) {
		f := NewFile()
		format := []ConditionalFormatOptions{{
			Type:     "data_bar",
			Criteria: "=",
			MinType:  "min",
			MaxType:  "max",
			BarColor: "#638EC6",
		}}
		assert.NoError(t, f.SetConditionalFormat("Sheet1", "D2:E2", format))
		assert.NoError(t, f.SetConditionalFormat("Sheet1", "F2", format))
		assert.NoError(t, f.RemoveRow("Sheet1", 2))
		opts, err := f.GetConditionalFormats("Sheet1")
		assert.NoError(t, err)
		assert.Len(t, opts, 0)
	})
	t.Run("for_adjust_conditional_formats_row", func(t *testing.T) {
		f := NewFile()
		format := []ConditionalFormatOptions{{
			Type:     "data_bar",
			Criteria: "=",
			MinType:  "min",
			MaxType:  "max",
			BarColor: "#638EC6",
		}}
		assert.NoError(t, f.SetConditionalFormat("Sheet1", "D2:D3", format))
		assert.NoError(t, f.SetConditionalFormat("Sheet1", "D5", format))
		assert.NoError(t, f.RemoveRow("Sheet1", 1))
		opts, err := f.GetConditionalFormats("Sheet1")
		assert.NoError(t, err)
		assert.Len(t, opts, 2)
		assert.Equal(t, format, opts["D1:D2"])
		assert.Equal(t, format, opts["D4:D4"])
	})
}

func TestAdjustDataValidations(t *testing.T) {
	f := NewFile()
	dv := NewDataValidation(true)
	dv.Sqref = "B1"
	assert.NoError(t, dv.SetDropList([]string{"1", "2", "3"}))
	assert.NoError(t, f.AddDataValidation("Sheet1", dv))
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))
	dvs, err := f.GetDataValidations("Sheet1")
	assert.NoError(t, err)
	assert.Len(t, dvs, 0)

	assert.NoError(t, f.SetCellValue("Sheet1", "F2", 1))
	assert.NoError(t, f.SetCellValue("Sheet1", "F3", 2))
	dv = NewDataValidation(true)
	dv.Sqref = "C2:D3"
	dv.SetSqrefDropList("$F$2:$F$3")
	assert.NoError(t, f.AddDataValidation("Sheet1", dv))

	assert.NoError(t, f.AddChartSheet("Chart1", &Chart{Type: Line}))
	_, err = f.NewSheet("Sheet2")
	assert.NoError(t, err)
	assert.NoError(t, f.SetSheetRow("Sheet2", "C1", &[]interface{}{1, 10}))
	dv = NewDataValidation(true)
	dv.Sqref = "C5:D6"
	assert.NoError(t, dv.SetRange("Sheet2!C1", "Sheet2!D1", DataValidationTypeWhole, DataValidationOperatorBetween))
	dv.SetError(DataValidationErrorStyleStop, "error title", "error body")
	assert.NoError(t, f.AddDataValidation("Sheet1", dv))
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))
	assert.NoError(t, f.RemoveCol("Sheet2", "B"))
	dvs, err = f.GetDataValidations("Sheet1")
	assert.NoError(t, err)
	assert.Equal(t, "B2:C3", dvs[0].Sqref)
	assert.Equal(t, "$E$2:$E$3", dvs[0].Formula1)
	assert.Equal(t, "B5:C6", dvs[1].Sqref)
	assert.Equal(t, "Sheet2!B1", dvs[1].Formula1)
	assert.Equal(t, "Sheet2!C1", dvs[1].Formula2)

	dv = NewDataValidation(true)
	dv.Sqref = "C8:D10"
	assert.NoError(t, dv.SetDropList([]string{`A<`, `B>`, `C"`, "D\t", `E'`, `F`}))
	assert.NoError(t, f.AddDataValidation("Sheet1", dv))
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))
	dvs, err = f.GetDataValidations("Sheet1")
	assert.NoError(t, err)
	assert.Equal(t, "\"A<,B>,C\",D\t,E',F\"", dvs[2].Formula1)

	// Test adjust data validation with multiple cell range
	dv = NewDataValidation(true)
	dv.Sqref = "G1:G3 H1:H3 A3:A1048576"
	assert.NoError(t, dv.SetDropList([]string{"1", "2", "3"}))
	assert.NoError(t, f.AddDataValidation("Sheet1", dv))
	assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
	dvs, err = f.GetDataValidations("Sheet1")
	assert.NoError(t, err)
	assert.Equal(t, "G1:G4 H1:H4 A4:A1048576", dvs[3].Sqref)

	dv = NewDataValidation(true)
	dv.Sqref = "C5:D6"
	assert.NoError(t, dv.SetRange("Sheet1!A1048576", "Sheet1!XFD1", DataValidationTypeWhole, DataValidationOperatorBetween))
	dv.SetError(DataValidationErrorStyleStop, "error title", "error body")
	assert.NoError(t, f.AddDataValidation("Sheet1", dv))
	assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))
	assert.Equal(t, ErrMaxRows, f.InsertRows("Sheet1", 1, 1))

	ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
	assert.True(t, ok)
	ws.(*xlsxWorksheet).DataValidations.DataValidation[0].Sqref = "-"
	assert.Equal(t, newCellNameToCoordinatesError("-", newInvalidCellNameError("-")), f.RemoveCol("Sheet1", "B"))

	ws.(*xlsxWorksheet).DataValidations.DataValidation[0] = nil
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))

	ws.(*xlsxWorksheet).DataValidations = nil
	assert.NoError(t, f.RemoveCol("Sheet1", "B"))

	f.Sheet.Delete("xl/worksheets/sheet1.xml")
	f.Pkg.Store("xl/worksheets/sheet1.xml", MacintoshCyrillicCharset)
	assert.EqualError(t, f.adjustDataValidations(nil, "Sheet1", columns, 0, 0, 1), "XML syntax error on line 1: invalid UTF-8")

	t.Run("for_escaped_data_validation_rules_formula", func(t *testing.T) {
		f := NewFile()
		_, err := f.NewSheet("Sheet2")
		assert.NoError(t, err)
		dv := NewDataValidation(true)
		dv.Sqref = "A1"
		assert.NoError(t, dv.SetDropList([]string{"option1", strings.Repeat("\"", 4)}))
		ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
		assert.True(t, ok)
		assert.NoError(t, f.AddDataValidation("Sheet1", dv))
		// The double quote symbol in none formula data validation rules will be escaped in the Kingsoft WPS Office
		formula := strings.ReplaceAll(fmt.Sprintf("\"option1, %s", strings.Repeat("\"", 9)), "\"", "&quot;")
		ws.(*xlsxWorksheet).DataValidations.DataValidation[0].Formula1.Content = formula
		assert.NoError(t, f.RemoveCol("Sheet2", "A"))
		dvs, err := f.GetDataValidations("Sheet1")
		assert.NoError(t, err)
		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) {
	f := NewFile()
	// Test add pictures to sheet with positioning
	assert.NoError(t, f.AddPicture("Sheet1", "B2", filepath.Join("test", "images", "excel.jpg"), nil))
	assert.NoError(t, f.AddPicture("Sheet1", "B11", filepath.Join("test", "images", "excel.jpg"), &GraphicOptions{Positioning: "oneCell"}))
	assert.NoError(t, f.AddPicture("Sheet1", "B21", filepath.Join("test", "images", "excel.jpg"), &GraphicOptions{Positioning: "absolute"}))

	// Test adjust pictures on inserting columns and rows
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 5, 1))
	assert.NoError(t, f.InsertRows("Sheet1", 15, 1))
	cells, err := f.GetPictureCells("Sheet1")
	assert.NoError(t, err)
	assert.Equal(t, []string{"D3", "B21", "D13"}, cells)
	wb := filepath.Join("test", "TestAdjustDrawings.xlsx")
	assert.NoError(t, f.SaveAs(wb))

	// Test adjust pictures on deleting columns and rows
	assert.NoError(t, f.RemoveCol("Sheet1", "A"))
	assert.NoError(t, f.RemoveRow("Sheet1", 1))
	cells, err = f.GetPictureCells("Sheet1")
	assert.NoError(t, err)
	assert.Equal(t, []string{"C2", "B21", "C12"}, cells)

	// Test adjust existing pictures on inserting columns and rows
	f, err = OpenFile(wb)
	assert.NoError(t, err)
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 5, 1))
	assert.NoError(t, f.InsertRows("Sheet1", 16, 1))
	cells, err = f.GetPictureCells("Sheet1")
	assert.NoError(t, err)
	assert.Equal(t, []string{"F4", "B21", "F15"}, cells)

	// Test adjust drawings with unsupported charset
	f, err = OpenFile(wb)
	assert.NoError(t, err)
	f.Pkg.Store("xl/drawings/drawing1.xml", MacintoshCyrillicCharset)
	assert.EqualError(t, f.InsertCols("Sheet1", "A", 1), "XML syntax error on line 1: invalid UTF-8")

	errors := []error{ErrColumnNumber, ErrColumnNumber, ErrMaxRows, ErrMaxRows}
	cells = []string{"XFD1", "XFB1"}
	for i, cell := range cells {
		f = NewFile()
		assert.NoError(t, f.AddPicture("Sheet1", cell, filepath.Join("test", "images", "excel.jpg"), nil))
		assert.Equal(t, errors[i], f.InsertCols("Sheet1", "A", 1))
		assert.NoError(t, f.SaveAs(wb))
		f, err = OpenFile(wb)
		assert.NoError(t, err)
		assert.Equal(t, errors[i], f.InsertCols("Sheet1", "A", 1))
	}
	errors = []error{ErrMaxRows, ErrMaxRows}
	cells = []string{"A1048576", "A1048570"}
	for i, cell := range cells {
		f = NewFile()
		assert.NoError(t, f.AddPicture("Sheet1", cell, filepath.Join("test", "images", "excel.jpg"), nil))
		assert.Equal(t, errors[i], f.InsertRows("Sheet1", 1, 1))
		assert.NoError(t, f.SaveAs(wb))
		f, err = OpenFile(wb)
		assert.NoError(t, err)
		assert.Equal(t, errors[i], f.InsertRows("Sheet1", 1, 1))
	}

	a := xdrCellAnchor{}
	assert.NoError(t, a.adjustDrawings(columns, 0, 0))
	p := xlsxCellAnchorPos{}
	assert.NoError(t, p.adjustDrawings(columns, 0, 0, ""))

	f, err = OpenFile(wb)
	assert.NoError(t, err)
	f.Pkg.Store("xl/drawings/drawing1.xml", []byte(xml.Header+`<wsDr xmlns="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"><twoCellAnchor><from><col>0</col><colOff>0</colOff><row>0</row><rowOff>0</rowOff></from><to><col>1</col><colOff>0</colOff><row>1</row><rowOff>0</rowOff></to><mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"></mc:AlternateContent><clientData/></twoCellAnchor></wsDr>`))
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))

	f, err = OpenFile(wb)
	assert.NoError(t, err)
	f.Pkg.Store("xl/drawings/drawing1.xml", []byte(xml.Header+fmt.Sprintf(`<wsDr xmlns="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"><oneCellAnchor><from><col>%d</col><row>0</row></from><mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"></mc:AlternateContent><clientData/></oneCellAnchor></wsDr>`, MaxColumns)))
	assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))
}

func TestAdjustDefinedNames(t *testing.T) {
	f := NewFile()
	_, err := f.NewSheet("Sheet2")
	assert.NoError(t, err)
	for _, dn := range []*DefinedName{
		{Name: "Name1", RefersTo: "Sheet1!$XFD$1"},
		{Name: "Name2", RefersTo: "Sheet2!$C$1", Scope: "Sheet1"},
		{Name: "Name3", RefersTo: "Sheet2!$C$1:$D$2", Scope: "Sheet1"},
		{Name: "Name4", RefersTo: "Sheet2!$C1:D$2"},
		{Name: "Name5", RefersTo: "Sheet2!C$1:$D2"},
		{Name: "Name6", RefersTo: "Sheet2!C:$D"},
		{Name: "Name7", RefersTo: "Sheet2!$C:D"},
		{Name: "Name8", RefersTo: "Sheet2!C:D"},
		{Name: "Name9", RefersTo: "Sheet2!$C:$D"},
		{Name: "Name10", RefersTo: "Sheet2!1:2"},
	} {
		assert.NoError(t, f.SetDefinedName(dn))
	}
	assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
	assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
	assert.NoError(t, f.InsertCols("Sheet2", "A", 1))
	assert.NoError(t, f.InsertRows("Sheet2", 1, 1))
	definedNames := f.GetDefinedName()
	for i, expected := range []string{
		"Sheet1!$XFD$2",
		"Sheet2!$D$2",
		"Sheet2!$D$2:$E$3",
		"Sheet2!$D1:D$3",
		"Sheet2!C$2:$E2",
		"Sheet2!C:$E",
		"Sheet2!$D:D",
		"Sheet2!C:D",
		"Sheet2!$D:$E",
		"Sheet2!1:2",
	} {
		assert.Equal(t, expected, definedNames[i].RefersTo)
	}

	f = NewFile()
	assert.NoError(t, f.SetDefinedName(&DefinedName{
		Name:     "Name1",
		RefersTo: "Sheet1!$A$1",
		Scope:    "Sheet1",
	}))
	assert.NoError(t, f.RemoveCol("Sheet1", "A"))
	definedNames = f.GetDefinedName()
	assert.Equal(t, "Sheet1!$A$1", definedNames[0].RefersTo)

	f = NewFile()
	assert.NoError(t, f.SetDefinedName(&DefinedName{
		Name:     "Name1",
		RefersTo: "'1.A & B C'!#REF!",
		Scope:    "Sheet1",
	}))
	assert.NoError(t, f.RemoveCol("Sheet1", "A"))
	definedNames = f.GetDefinedName()
	assert.Equal(t, "'1.A & B C'!#REF!", definedNames[0].RefersTo)

	f = NewFile()
	f.WorkBook = nil
	f.Pkg.Store(defaultXMLPathWorkbook, MacintoshCyrillicCharset)
	assert.EqualError(t, f.adjustDefinedNames("Sheet1", columns, 0, 0), "XML syntax error on line 1: invalid UTF-8")
}


================================================
FILE: calc.go
================================================
// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to 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.25.0 or later.

package excelize

import (
	"bytes"
	"container/list"
	"errors"
	"fmt"
	"math"
	"math/big"
	"math/cmplx"
	"math/rand"
	"net/url"
	"reflect"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
	"unicode"
	"unicode/utf8"
	"unsafe"

	"github.com/xuri/efp"
	"golang.org/x/text/language"
	"golang.org/x/text/message"
)

const (
	// Excel formula errors
	formulaErrorDIV         = "#DIV/0!"
	formulaErrorNAME        = "#NAME?"
	formulaErrorNA          = "#N/A"
	formulaErrorNUM         = "#NUM!"
	formulaErrorVALUE       = "#VALUE!"
	formulaErrorREF         = "#REF!"
	formulaErrorNULL        = "#NULL!"
	formulaErrorSPILL       = "#SPILL!"
	formulaErrorCALC        = "#CALC!"
	formulaErrorGETTINGDATA = "#GETTING_DATA"
	// Formula criteria condition enumeration
	_ byte = iota
	criteriaEq
	criteriaLe
	criteriaGe
	criteriaNe
	criteriaL
	criteriaG
	criteriaErr
	criteriaRegexp

	categoryWeightAndMass
	categoryDistance
	categoryTime
	categoryPressure
	categoryForce
	categoryEnergy
	categoryPower
	categoryMagnetism
	categoryTemperature
	categoryVolumeAndLiquidMeasure
	categoryArea
	categoryInformation
	categorySpeed

	matchModeExact      = 0
	matchModeMinGreater = 1
	matchModeMaxLess    = -1
	matchModeWildcard   = 2

	searchModeLinear        = 1
	searchModeReverseLinear = -1
	searchModeAscBinary     = 2
	searchModeDescBinary    = -2

	maxFinancialIterations = 128
	financialPrecision     = 1.0e-08
	// Date and time format regular expressions
	monthRe    = `((jan|january)|(feb|february)|(mar|march)|(apr|april)|(may)|(jun|june)|(jul|july)|(aug|august)|(sep|september)|(oct|october)|(nov|november)|(dec|december))`
	df1        = `(([0-9])+)/(([0-9])+)/(([0-9])+)`
	df2        = monthRe + ` (([0-9])+), (([0-9])+)`
	df3        = `(([0-9])+)-(([0-9])+)-(([0-9])+)`
	df4        = `(([0-9])+)-` + monthRe + `-(([0-9])+)`
	datePrefix = `^((` + df1 + `|` + df2 + `|` + df3 + `|` + df4 + `) )?`
	tfhh       = `(([0-9])+) (am|pm)`
	tfhhmm     = `(([0-9])+):(([0-9])+)( (am|pm))?`
	tfmmss     = `(([0-9])+):(([0-9])+\.([0-9])+)( (am|pm))?`
	tfhhmmss   = `(([0-9])+):(([0-9])+):(([0-9])+(\.([0-9])+)?)( (am|pm))?`
	timeSuffix = `( (` + tfhh + `|` + tfhhmm + `|` + tfmmss + `|` + tfhhmmss + `))?$`
)

var (
	// wildcardTokenRE tokenizes an Excel wildcard pattern into tilde-escaped
	// sequences, bare wildcards (* ?), or any other single character.
	wildcardTokenRE = regexp.MustCompile(`~[*?~]|[*?]|[\s\S]`)
	// wildcardPatternMap maps each token produced by wildcardTokenRE to its
	// regular-expression equivalent. Tokens absent from the map are literals.
	wildcardPatternMap = map[string]string{
		"~*": regexp.QuoteMeta("*"),
		"~?": regexp.QuoteMeta("?"),
		"~~": regexp.QuoteMeta("~"),
		"*":  ".*",
		"?":  ".",
	}
	// wildcardBareTokens is the set of tokens that represent real wildcards.
	wildcardBareTokens = map[string]bool{"*": true, "?": true}
	// tokenPriority defined basic arithmetic operator priority
	tokenPriority = map[string]int{
		"^":  5,
		"*":  4,
		"/":  4,
		"+":  3,
		"-":  3,
		"&":  2,
		"=":  1,
		"<>": 1,
		"<":  1,
		"<=": 1,
		">":  1,
		">=": 1,
	}
	month2num = map[string]int{
		"january":   1,
		"february":  2,
		"march":     3,
		"april":     4,
		"may":       5,
		"june":      6,
		"july":      7,
		"august":    8,
		"september": 9,
		"october":   10,
		"november":  11,
		"december":  12,
		"jan":       1,
		"feb":       2,
		"mar":       3,
		"apr":       4,
		"jun":       6,
		"jul":       7,
		"aug":       8,
		"sep":       9,
		"oct":       10,
		"nov":       11,
		"dec":       12,
	}
	dateFormats = map[string]*regexp.Regexp{
		"mm/dd/yy":    regexp.MustCompile(`^` + df1 + timeSuffix),
		"mm dd, yy":   regexp.MustCompile(`^` + df2 + timeSuffix),
		"yy-mm-dd":    regexp.MustCompile(`^` + df3 + timeSuffix),
		"yy-mmStr-dd": regexp.MustCompile(`^` + df4 + timeSuffix),
	}
	timeFormats = map[string]*regexp.Regexp{
		"hh":       regexp.MustCompile(datePrefix + tfhh + `$`),
		"hh:mm":    regexp.MustCompile(datePrefix + tfhhmm + `$`),
		"mm:ss":    regexp.MustCompile(datePrefix + tfmmss + `$`),
		"hh:mm:ss": regexp.MustCompile(datePrefix + tfhhmmss + `$`),
	}
	dateOnlyFormats = []*regexp.Regexp{
		regexp.MustCompile(`^` + df1 + `$`),
		regexp.MustCompile(`^` + df2 + `$`),
		regexp.MustCompile(`^` + df3 + `$`),
		regexp.MustCompile(`^` + df4 + `$`),
	}
	addressFmtMaps = map[string]func(col, row int) (string, error){
		"1_TRUE": func(col, row int) (string, error) {
			return CoordinatesToCellName(col, row, true)
		},
		"1_FALSE": func(col, row int) (string, error) {
			return fmt.Sprintf("R%dC%d", row, col), nil
		},
		"2_TRUE": func(col, row int) (string, error) {
			column, err := ColumnNumberToName(col)
			if err != nil {
				return "", err
			}
			return fmt.Sprintf("%s$%d", column, row), nil
		},
		"2_FALSE": func(col, row int) (string, error) {
			return fmt.Sprintf("R%dC[%d]", row, col), nil
		},
		"3_TRUE": func(col, row int) (string, error) {
			column, err := ColumnNumberToName(col)
			if err != nil {
				return "", err
			}
			return fmt.Sprintf("$%s%d", column, row), nil
		},
		"3_FALSE": func(col, row int) (string, error) {
			return fmt.Sprintf("R[%d]C%d", row, col), nil
		},
		"4_TRUE": func(col, row int) (string, error) {
			return CoordinatesToCellName(col, row, false)
		},
		"4_FALSE": func(col, row int) (string, error) {
			return fmt.Sprintf("R[%d]C[%d]", row, col), nil
		},
	}
	formulaFnNameReplacer = strings.NewReplacer("_xlfn.", "", ".", "dot")
	formulaFormats        = []*regexp.Regexp{
		regexp.MustCompile(`^(\d+)$`),
		regexp.MustCompile(`^=(.*)$`),
		regexp.MustCompile(`^<>(.*)$`),
		regexp.MustCompile(`^<=(.*)$`),
		regexp.MustCompile(`^>=(.*)$`),
		regexp.MustCompile(`^<(.*)$`),
		regexp.MustCompile(`^>(.*)$`),
	}
	formulaCriterias = []byte{
		criteriaEq,
		criteriaEq,
		criteriaNe,
		criteriaLe,
		criteriaGe,
		criteriaL,
		criteriaG,
	}
	// defines numbers text in the Thai used for the BAHTTEXT formula function.
	th0      = "\u0E28\u0E39\u0E19\u0E22\u0E4C"
	th1      = "\u0E2B\u0E19\u0E36\u0E48\u0E07"
	th2      = "\u0E2A\u0E2D\u0E07"
	th3      = "\u0E2A\u0E32\u0E21"
	th4      = "\u0E2A\u0E35\u0E48"
	th5      = "\u0E2B\u0E49\u0E32"
	th6      = "\u0E2B\u0E01"
	th7      = "\u0E40\u0E08\u0E47\u0E14"
	th8      = "\u0E41\u0E1B\u0E14"
	th9      = "\u0E40\u0E01\u0E49\u0E32"
	th10     = "\u0E2A\u0E34\u0E1A"
	th11     = "\u0E40\u0E2D\u0E47\u0E14"
	th20     = "\u0E22\u0E35\u0E48"
	th1e2    = "\u0E23\u0E49\u0E2D\u0E22"
	th1e3    = "\u0E1E\u0E31\u0E19"
	th1e4    = "\u0E2B\u0E21\u0E37\u0E48\u0E19"
	th1e5    = "\u0E41\u0E2A\u0E19"
	th1e6    = "\u0E25\u0E49\u0E32\u0E19"
	thDot0   = "\u0E16\u0E49\u0E27\u0E19"
	thBaht   = "\u0E1A\u0E32\u0E17"
	thSatang = "\u0E2A\u0E15\u0E32\u0E07\u0E04\u0E4C"
	thMinus  = "\u0E25\u0E1A"
)

// calcContext defines the formula execution context.
type calcContext struct {
	mu                sync.Mutex
	entry             string
	maxCalcIterations uint
	iterations        map[string]uint
	iterationsCache   map[string]formulaArg
}

// cellRef defines the structure of a cell reference.
type cellRef struct {
	Col   int
	Row   int
	Sheet string
}

// cellRef defines the structure of a cell range.
type cellRange struct {
	From cellRef
	To   cellRef
}

// formulaCriteria defined formula criteria parser result.
type formulaCriteria struct {
	Type      byte
	Condition formulaArg
}

// ArgType is the type of formula argument type.
type ArgType byte

// Formula argument types enumeration.
const (
	ArgUnknown ArgType = iota
	ArgNumber
	ArgString
	ArgList
	ArgMatrix
	ArgError
	ArgEmpty
)

// formulaArg is the argument of a formula or function.
type formulaArg struct {
	SheetName            string
	Number               float64
	String               string
	List                 []formulaArg
	Matrix               [][]formulaArg
	Boolean              bool
	Error                string
	Type                 ArgType
	cellRefs, cellRanges *list.List
}

// Value returns a string data type of the formula argument.
func (fa formulaArg) Value() (value string) {
	switch fa.Type {
	case ArgNumber:
		if fa.Boolean {
			if fa.Number == 0 {
				return "FALSE"
			}
			return "TRUE"
		}
		return fmt.Sprintf("%g", fa.Number)
	case ArgString:
		return fa.String
	case ArgMatrix:
		if args := fa.ToList(); len(args) > 0 {
			return args[0].Value()
		}
	case ArgError:
		return fa.Error
	}
	return
}

// ToNumber returns a formula argument with number data type.
func (fa formulaArg) ToNumber() formulaArg {
	var n float64
	var err error
	switch fa.Type {
	case ArgString:
		n, err = strconv.ParseFloat(fa.String, 64)
		if err != nil {
			return newErrorFormulaArg(formulaErrorVALUE, err.Error())
		}
	case ArgNumber:
		n = fa.Number
	case ArgMatrix:
		if args := fa.ToList(); len(args) > 0 {
			return args[0].ToNumber()
		}
	}
	return newNumberFormulaArg(n)
}

// ToBool returns a formula argument with boolean data type.
func (fa formulaArg) ToBool() formulaArg {
	var b bool
	var err error
	switch fa.Type {
	case ArgString:
		b, err = strconv.ParseBool(fa.String)
		if err != nil {
			return newErrorFormulaArg(formulaErrorVALUE, err.Error())
		}
	case ArgNumber:
		if fa.Number == 1 {
			b = true
		}
	}
	return newBoolFormulaArg(b)
}

// ToList returns a formula argument with array data type.
func (fa formulaArg) ToList() []formulaArg {
	switch fa.Type {
	case ArgMatrix:
		var args []formulaArg
		for _, row := range fa.Matrix {
			args = append(args, row...)
		}
		return args
	case ArgList:
		return fa.List
	case ArgNumber, ArgString, ArgError, ArgUnknown:
		return []formulaArg{fa}
	}
	return nil
}

// formulaFuncs is the type of the formula functions.
type formulaFuncs struct {
	f           *File
	ctx         *calcContext
	sheet, cell string
}

// implicitIntersect applies Excel's implicit intersection to a matrix argument.
// For a non-array formula, when a whole-column or whole-row reference is passed
// to a scalar function, Excel resolves it to the single cell in the same row
// (or column) as the formula cell. If the argument is not a matrix, it is
// returned unchanged.
func (fn *formulaFuncs) implicitIntersect(arg formulaArg) formulaArg {
	if arg.Type != ArgMatrix {
		return arg
	}
	_, row, err := CellNameToCoordinates(fn.cell)
	if err != nil {
		return arg
	}
	// row is 1-based; matrix is 0-indexed
	idx := row - 1
	if idx >= 0 && idx < len(arg.Matrix) && len(arg.Matrix[idx]) > 0 {
		return arg.Matrix[idx][0]
	}
	return arg
}

// CalcCellValue provides a function to get calculated cell value. This feature
// is currently in working processing. Iterative calculation, implicit
// intersection, explicit intersection, array formula, table formula and some
// other formulas are not supported currently.
//
// Supported formula functions:
//
//	ABS
//	ACCRINT
//	ACCRINTM
//	ACOS
//	ACOSH
//	ACOT
//	ACOTH
//	ADDRESS
//	AGGREGATE
//	AMORDEGRC
//	AMORLINC
//	AND
//	ARABIC
//	ARRAYTOTEXT
//	ASIN
//	ASINH
//	ATAN
//	ATAN2
//	ATANH
//	AVEDEV
//	AVERAGE
//	AVERAGEA
//	AVERAGEIF
//	AVERAGEIFS
//	BAHTTEXT
//	BASE
//	BESSELI
//	BESSELJ
//	BESSELK
//	BESSELY
//	BETA.DIST
//	BETA.INV
//	BETADIST
//	BETAINV
//	BIN2DEC
//	BIN2HEX
//	BIN2OCT
//	BINOM.DIST
//	BINOM.DIST.RANGE
//	BINOM.INV
//	BINOMDIST
//	BITAND
//	BITLSHIFT
//	BITOR
//	BITRSHIFT
//	BITXOR
//	CEILING
//	CEILING.MATH
//	CEILING.PRECISE
//	CHAR
//	CHIDIST
//	CHIINV
//	CHISQ.DIST
//	CHISQ.DIST.RT
//	CHISQ.INV
//	CHISQ.INV.RT
//	CHISQ.TEST
//	CHITEST
//	CHOOSE
//	CLEAN
//	CODE
//	COLUMN
//	COLUMNS
//	COMBIN
//	COMBINA
//	COMPLEX
//	CONCAT
//	CONCATENATE
//	CONFIDENCE
//	CONFIDENCE.NORM
//	CONFIDENCE.T
//	CONVERT
//	CORREL
//	COS
//	COSH
//	COT
//	COTH
//	COUNT
//	COUNTA
//	COUNTBLANK
//	COUNTIF
//	COUNTIFS
//	COUPDAYBS
//	COUPDAYS
//	COUPDAYSNC
//	COUPNCD
//	COUPNUM
//	COUPPCD
//	COVAR
//	COVARIANCE.P
//	COVARIANCE.S
//	CRITBINOM
//	CSC
//	CSCH
//	CUMIPMT
//	CUMPRINC
//	DATE
//	DATEDIF
//	DATEVALUE
//	DAVERAGE
//	DAY
//	DAYS
//	DAYS360
//	DB
//	DBCS
//	DCOUNT
//	DCOUNTA
//	DDB
//	DEC2BIN
//	DEC2HEX
//	DEC2OCT
//	DECIMAL
//	DEGREES
//	DELTA
//	DEVSQ
//	DGET
//	DISC
//	DMAX
//	DMIN
//	DOLLAR
//	DOLLARDE
//	DOLLARFR
//	DPRODUCT
//	DSTDEV
//	DSTDEVP
//	DSUM
//	DURATION
//	DVAR
//	DVARP
//	EDATE
//	EFFECT
//	ENCODEURL
//	EOMONTH
//	ERF
//	ERF.PRECISE
//	ERFC
//	ERFC.PRECISE
//	ERROR.TYPE
//	EUROCONVERT
//	EVEN
//	EXACT
//	EXP
//	EXPON.DIST
//	EXPONDIST
//	F.DIST
//	F.DIST.RT
//	F.INV
//	F.INV.RT
//	F.TEST
//	FACT
//	FACTDOUBLE
//	FALSE
//	FDIST
//	FIND
//	FINDB
//	FINV
//	FISHER
//	FISHERINV
//	FIXED
//	FLOOR
//	FLOOR.MATH
//	FLOOR.PRECISE
//	FORECAST
//	FORECAST.LINEAR
//	FORMULATEXT
//	FREQUENCY
//	FTEST
//	FV
//	FVSCHEDULE
//	GAMMA
//	GAMMA.DIST
//	GAMMA.INV
//	GAMMADIST
//	GAMMAINV
//	GAMMALN
//	GAMMALN.PRECISE
//	GAUSS
//	GCD
//	GEOMEAN
//	GESTEP
//	GROWTH
//	HARMEAN
//	HEX2BIN
//	HEX2DEC
//	HEX2OCT
//	HLOOKUP
//	HOUR
//	HYPERLINK
//	HYPGEOM.DIST
//	HYPGEOMDIST
//	IF
//	IFERROR
//	IFNA
//	IFS
//	IMABS
//	IMAGINARY
//	IMARGUMENT
//	IMCONJUGATE
//	IMCOS
//	IMCOSH
//	IMCOT
//	IMCSC
//	IMCSCH
//	IMDIV
//	IMEXP
//	IMLN
//	IMLOG10
//	IMLOG2
//	IMPOWER
//	IMPRODUCT
//	IMREAL
//	IMSEC
//	IMSECH
//	IMSIN
//	IMSINH
//	IMSQRT
//	IMSUB
//	IMSUM
//	IMTAN
//	INDEX
//	INDIRECT
//	INT
//	INTERCEPT
//	INTRATE
//	IPMT
//	IRR
//	ISBLANK
//	ISERR
//	ISERROR
//	ISEVEN
//	ISFORMULA
//	ISLOGICAL
//	ISNA
//	ISNONTEXT
//	ISNUMBER
//	ISO.CEILING
//	ISODD
//	ISOWEEKNUM
//	ISPMT
//	ISREF
//	ISTEXT
//	KURT
//	LARGE
//	LCM
//	LEFT
//	LEFTB
//	LEN
//	LENB
//	LN
//	LOG
//	LOG10
//	LOGINV
//	LOGNORM.DIST
//	LOGNORM.INV
//	LOGNORMDIST
//	LOOKUP
//	LOWER
//	MATCH
//	MAX
//	MAXA
//	MAXIFS
//	MDETERM
//	MDURATION
//	MEDIAN
//	MID
//	MIDB
//	MIN
//	MINA
//	MINIFS
//	MINUTE
//	MINVERSE
//	MIRR
//	MMULT
//	MOD
//	MODE
//	MODE.MULT
//	MODE.SNGL
//	MONTH
//	MROUND
//	MULTINOMIAL
//	MUNIT
//	N
//	NA
//	NEGBINOM.DIST
//	NEGBINOMDIST
//	NETWORKDAYS
//	NETWORKDAYS.INTL
//	NOMINAL
//	NORM.DIST
//	NORM.INV
//	NORM.S.DIST
//	NORM.S.INV
//	NORMDIST
//	NORMINV
//	NORMSDIST
//	NORMSINV
//	NOT
//	NOW
//	NPER
//	NPV
//	OCT2BIN
//	OCT2DEC
//	OCT2HEX
//	ODD
//	ODDFPRICE
//	ODDFYIELD
//	ODDLPRICE
//	ODDLYIELD
//	OR
//	PDURATION
//	PEARSON
//	PERCENTILE
//	PERCENTILE.EXC
//	PERCENTILE.INC
//	PERCENTRANK
//	PERCENTRANK.EXC
//	PERCENTRANK.INC
//	PERMUT
//	PERMUTATIONA
//	PHI
//	PI
//	PMT
//	POISSON
//	POISSON.DIST
//	POWER
//	PPMT
//	PRICE
//	PRICEDISC
//	PRICEMAT
//	PROB
//	PRODUCT
//	PROPER
//	PV
//	QUARTILE
//	QUARTILE.EXC
//	QUARTILE.INC
//	QUOTIENT
//	RADIANS
//	RAND
//	RANDBETWEEN
//	RANK
//	RANK.EQ
//	RATE
//	RECEIVED
//	REPLACE
//	REPLACEB
//	REPT
//	RIGHT
//	RIGHTB
//	ROMAN
//	ROUND
//	ROUNDDOWN
//	ROUNDUP
//	ROW
//	ROWS
//	RRI
//	RSQ
//	SEARCH
//	SEARCHB
//	SEC
//	SECH
//	SECOND
//	SERIESSUM
//	SHEET
//	SHEETS
//	SIGN
//	SIN
//	SINH
//	SKEW
//	SKEW.P
//	SLN
//	SLOPE
//	SMALL
//	SORTBY
//	SQRT
//	SQRTPI
//	STANDARDIZE
//	STDEV
//	STDEV.P
//	STDEV.S
//	STDEVA
//	STDEVP
//	STDEVPA
//	STEYX
//	SUBSTITUTE
//	SUBTOTAL
//	SUM
//	SUMIF
//	SUMIFS
//	SUMPRODUCT
//	SUMSQ
//	SUMX2MY2
//	SUMX2PY2
//	SUMXMY2
//	SWITCH
//	SYD
//	T
//	T.DIST
//	T.DIST.2T
//	T.DIST.RT
//	T.INV
//	T.INV.2T
//	T.TEST
//	TAN
//	TANH
//	TBILLEQ
//	TBILLPRICE
//	TBILLYIELD
//	TDIST
//	TEXT
//	TEXTAFTER
//	TEXTBEFORE
//	TEXTJOIN
//	TIME
//	TIMEVALUE
//	TINV
//	TODAY
//	TRANSPOSE
//	TREND
//	TRIM
//	TRIMMEAN
//	TRUE
//	TRUNC
//	TTEST
//	TYPE
//	UNICHAR
//	UNICODE
//	UNIQUE
//	UPPER
//	VALUE
//	VALUETOTEXT
//	VAR
//	VAR.P
//	VAR.S
//	VARA
//	VARP
//	VARPA
//	VDB
//	VLOOKUP
//	WEEKDAY
//	WEEKNUM
//	WEIBULL
//	WEIBULL.DIST
//	WORKDAY
//	WORKDAY.INTL
//	XIRR
//	XLOOKUP
//	XNPV
//	XOR
//	YEAR
//	YEARFRAC
//	YIELD
//	YIELDDISC
//	YIELDMAT
//	Z.TEST
//	ZTEST
func (f *File) CalcCellValue(sheet, cell string, opts ...Options) (result string, err error) {
	entry := sheet + "!" + cell
	if cachedResult, ok := f.calcCache.Load(entry); ok {
		return cachedResult.(string), nil
	}
	options := f.getOptions(opts...)
	var (
		rawCellValue = options.RawCellValue
		styleIdx     int
		token        formulaArg
	)
	if token, err = f.calcCellValue(&calcContext{
		entry:             entry,
		maxCalcIterations: options.MaxCalcIterations,
		iterations:        make(map[string]uint),
		iterationsCache:   make(map[string]formulaArg),
	}, sheet, cell); err != nil {
		result = token.String
		return
	}
	if !rawCellValue {
		styleIdx, _ = f.GetCellStyle(sheet, cell)
	}
	if token.Type == ArgNumber && !token.Boolean {
		_, precision, decimal := isNumeric(token.Value())
		if precision > 15 {
			result, err = f.formattedValue(&xlsxC{S: styleIdx, V: strings.ToUpper(strconv.FormatFloat(decimal, 'G', 15, 64))}, rawCellValue, CellTypeNumber)
			if err == nil {
				f.calcCache.Store(entry, result)
			}
			return
		}
		if !strings.HasPrefix(result, "0") {
			result, err = f.formattedValue(&xlsxC{S: styleIdx, V: strings.ToUpper(strconv.FormatFloat(decimal, 'f', -1, 64))}, rawCellValue, CellTypeNumber)
		}
		if err == nil {
			f.calcCache.Store(entry, result)
		}
		return
	}
	result, err = f.formattedValue(&xlsxC{S: styleIdx, V: token.Value()}, rawCellValue, CellTypeInlineString)
	if err == nil {
		f.calcCache.Store(entry, result)
	}
	return
}

// clearCalcCache clear all calculation related caches.
func (f *File) clearCalcCache() {
	f.calcCache.Clear()
	f.formulaArgCache.Clear()
}

// calcCellValue calculate cell value by given context, worksheet name and cell
// reference.
func (f *File) calcCellValue(ctx *calcContext, sheet, cell string) (result formulaArg, err error) {
	var formula string
	if formula, err = f.getCellFormula(sheet, cell, true); err != nil {
		return
	}
	ps := efp.ExcelParser()
	tokens := ps.Parse(formula)
	if tokens == nil {
		return f.cellResolver(ctx, sheet, cell)
	}
	result, err = f.evalInfixExp(ctx, sheet, cell, tokens)
	return
}

// getPriority calculate arithmetic operator priority.
func getPriority(token efp.Token) (pri int) {
	pri = tokenPriority[token.TValue]
	if token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix {
		pri = 6
	}
	if isBeginParenthesesToken(token) { // (
		pri = 0
	}
	return
}

// newNumberFormulaArg constructs a number formula argument.
func newNumberFormulaArg(n float64) formulaArg {
	if math.IsNaN(n) {
		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
	}
	return formulaArg{Type: ArgNumber, Number: n}
}

// newStringFormulaArg constructs a string formula argument.
func newStringFormulaArg(s string) formulaArg {
	return formulaArg{Type: ArgString, String: s}
}

// newMatrixFormulaArg constructs a matrix formula argument.
func newMatrixFormulaArg(m [][]formulaArg) formulaArg {
	return formulaArg{Type: ArgMatrix, Matrix: m}
}

// newListFormulaArg create a list formula argument.
func newListFormulaArg(l []formulaArg) formulaArg {
	return formulaArg{Type: ArgList, List: l}
}

// newBoolFormulaArg constructs a boolean formula argument.
func newBoolFormulaArg(b bool) formulaArg {
	var n float64
	if b {
		n = 1
	}
	return formulaArg{Type: ArgNumber, Number: n, Boolean: true}
}

// newErrorFormulaArg create an error formula argument of a given type with a
// specified error message.
func newErrorFormulaArg(formulaError, msg string) formulaArg {
	return formulaArg{Type: ArgError, String: formulaError, Error: msg}
}

// newEmptyFormulaArg create an empty formula argument.
func newEmptyFormulaArg() formulaArg {
	return formulaArg{Type: ArgEmpty}
}

// evalInfixExp evaluate syntax analysis by given infix expression after
// lexical analysis. Evaluate an infix expression containing formulas by
// stacks:
//
//	opd  - Operand
//	opt  - Operator
//	opf  - Operation formula
//	opfd - Operand of the operation formula
//	opft - Operator of the operation formula
//	args - Arguments list of the operation formula
//
// TODO: handle subtypes: Nothing, Text, Logical, Error, Concatenation, Intersection, Union
func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens []efp.Token) (formulaArg, error) {
	var (
		err                             error
		inArray, inArrayRow             bool
		formulaArray                    [][]formulaArg
		formulaArrayRow                 []formulaArg
		opdStack, optStack, opfStack    = NewStack(), NewStack(), NewStack()
		opfdStack, opftStack, argsStack = NewStack(), NewStack(), NewStack()
	)
	for i := 0; i < len(tokens); i++ {
		token := tokens[i]

		// out of function stack
		if opfStack.Len() == 0 {
			if err = f.parseToken(ctx, sheet, token, opdStack, optStack); err != nil {
				return newEmptyFormulaArg(), err
			}
		}

		// function start
		if isFunctionStartToken(token) {
			if token.TValue == "ARRAY" {
				inArray, formulaArray = true, [][]formulaArg{}
				continue
			}
			if token.TValue == "ARRAYROW" {
				inArrayRow, formulaArrayRow = true, []formulaArg{}
				continue
			}
			opfStack.Push(token)
			argsStack.Push(list.New().Init())
			opftStack.Push(token) // to know which operators belong to a function use the function as a separator
			continue
		}

		// in function stack, walk 2 token at once
		if opfStack.Len() > 0 {
			var nextToken efp.Token
			if i+1 < len(tokens) {
				nextToken = tokens[i+1]
			}

			// current token is args or range, skip next token, order required: parse reference first
			if token.TSubType == efp.TokenSubTypeRange {
				if opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
					refTo := f.getDefinedNameRefTo(token.TValue, sheet)
					if refTo != "" {
						token.TValue = refTo
					}
					// parse reference: must reference at here
					result, err := f.parseReference(ctx, sheet, token.TValue)
					if err != nil {
						return result, err
					}
					opfdStack.Push(result)
					continue
				}
				if nextToken.TType == efp.TokenTypeArgument || nextToken.TType == efp.TokenTypeFunction {
					// parse reference: reference or range at here
					refTo := f.getDefinedNameRefTo(token.TValue, sheet)
					if refTo != "" {
						token.TValue = refTo
					}
					result, err := f.parseReference(ctx, sheet, token.TValue)
					if err != nil {
						return result, err
					}
					// when current token is range, next token is argument and opfdStack not empty,
					// should push value to opfdStack and continue
					if nextToken.TType == efp.TokenTypeArgument && !opfdStack.Empty() {
						opfdStack.Push(result)
						continue
					}
					argsStack.Peek().(*list.List).PushBack(result)
					continue
				}
			}

			// check current token is opft
			if err = f.parseToken(ctx, sheet, token, opfdStack, opftStack); err != nil {
				return newEmptyFormulaArg(), err
			}

			// current token is arg
			if token.TType == efp.TokenTypeArgument {
				for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
					// calculate trigger
					topOpt := opftStack.Peek().(efp.Token)
					if err := calculate(opfdStack, topOpt); err != nil {
						argsStack.Peek().(*list.List).PushFront(newErrorFormulaArg(formulaErrorVALUE, err.Error()))
					}
					opftStack.Pop()
				}
				if !opfdStack.Empty() {
					argsStack.Peek().(*list.List).PushBack(opfdStack.Pop().(formulaArg))
				}
				continue
			}

			if inArrayRow && isOperand(token) {
				formulaArrayRow = append(formulaArrayRow, opfdStack.Pop().(formulaArg))
				continue
			}
			if inArrayRow && isFunctionStopToken(token) {
				formulaArray = append(formulaArray, formulaArrayRow)
				inArrayRow = false
				continue
			}
			if inArray && isFunctionStopToken(token) {
				argsStack.Peek().(*list.List).PushBack(newMatrixFormulaArg(formulaArray))
				inArray = false
				continue
			}
			if errArg := f.evalInfixExpFunc(ctx, sheet, cell, token, nextToken, opfStack, opdStack, opftStack, opfdStack, argsStack); errArg.Type == ArgError {
				return errArg, errors.New(errArg.Error)
			}
		}
	}
	for optStack.Len() != 0 {
		topOpt := optStack.Peek().(efp.Token)
		if err = calculate(opdStack, topOpt); err != nil {
			return newEmptyFormulaArg(), err
		}
		optStack.Pop()
	}
	if opdStack.Len() == 0 {
		return newEmptyFormulaArg(), ErrInvalidFormula
	}
	return opdStack.Peek().(formulaArg), err
}

// evalInfixExpFunc evaluate formula function in the infix expression.
func (f *File) evalInfixExpFunc(ctx *calcContext, sheet, cell string, token, nextToken efp.Token, opfStack, opdStack, opftStack, opfdStack, argsStack *Stack) formulaArg {
	if !isFunctionStopToken(token) {
		return newEmptyFormulaArg()
	}
	prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack)
	// call formula function to evaluate
	arg := callFuncByName(&formulaFuncs{f: f, sheet: sheet, cell: cell, ctx: ctx},
		formulaFnNameReplacer.Replace(opfStack.Peek().(efp.Token).TValue),
		[]reflect.Value{reflect.ValueOf(argsStack.Peek().(*list.List))})
	if arg.Type == ArgError && opfStack.Len() == 1 {
		return arg
	}
	argsStack.Pop()
	opftStack.Pop() // remove current function separator
	opfStack.Pop()
	if opfStack.Len() > 0 { // still in function stack
		if nextToken.TType == efp.TokenTypeOperatorInfix || opftStack.Len() > 1 {
			// mathematics calculate in formula function
			opfdStack.Push(arg)
			return newEmptyFormulaArg()
		}
		argsStack.Peek().(*list.List).PushBack(arg)
		return newEmptyFormulaArg()
	}
	if arg.Type == ArgMatrix && len(arg.Matrix) > 0 && len(arg.Matrix[0]) > 0 {
		opdStack.Push(arg.Matrix[0][0])
		return newEmptyFormulaArg()
	}
	opdStack.Push(arg)
	return newEmptyFormulaArg()
}

// prepareEvalInfixExp check the token and stack state for formula function
// evaluate.
func prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack *Stack) {
	// current token is function stop
	for opftStack.Peek().(efp.Token) != opfStack.Peek().(efp.Token) {
		// calculate trigger
		topOpt := opftStack.Peek().(efp.Token)
		if err := calculate(opfdStack, topOpt); err != nil {
			argsStack.Peek().(*list.List).PushBack(newErrorFormulaArg(err.Error(), err.Error()))
			opftStack.Pop()
			continue
		}
		opftStack.Pop()
	}
	argument := true
	if opftStack.Len() > 2 && opfdStack.Len() == 1 {
		topOpt := opftStack.Pop()
		if opftStack.Peek().(efp.Token).TType == efp.TokenTypeOperatorInfix {
			argument = false
		}
		opftStack.Push(topOpt)
	}
	// push opfd to args
	if argument && opfdStack.Len() > 0 {
		argsStack.Peek().(*list.List).PushBack(opfdStack.Pop().(formulaArg))
	}
}

// calcPow evaluate exponentiation arithmetic operations.
func calcPow(rOpd, lOpd formulaArg, opdStack *Stack) error {
	lOpdVal := lOpd.ToNumber()
	if lOpdVal.Type != ArgNumber {
		return errors.New(lOpdVal.Value())
	}
	rOpdVal := rOpd.ToNumber()
	if rOpdVal.Type != ArgNumber {
		return errors.New(rOpdVal.Value())
	}
	opdStack.Push(newNumberFormulaArg(math.Pow(lOpdVal.Number, rOpdVal.Number)))
	return nil
}

// calcEq evaluate equal arithmetic operations.
func calcEq(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Type == ArgString && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(strings.EqualFold(lOpd.Value(), rOpd.Value())))
		return nil
	}
	opdStack.Push(newBoolFormulaArg(rOpd.Value() == lOpd.Value()))
	return nil
}

// calcNEq evaluate not equal arithmetic operations.
func calcNEq(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Type == ArgString && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(!strings.EqualFold(lOpd.Value(), rOpd.Value())))
		return nil
	}
	opdStack.Push(newBoolFormulaArg(rOpd.Value() != lOpd.Value()))
	return nil
}

// calcL evaluate less than arithmetic operations.
func calcL(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(lOpd.Number < rOpd.Number))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) == -1))
	}
	if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(false))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(true))
	}
	return nil
}

// calcLe evaluate less than or equal arithmetic operations.
func calcLe(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(lOpd.Number <= rOpd.Number))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) != 1))
	}
	if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(false))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(true))
	}
	return nil
}

// calcG evaluate greater than arithmetic operations.
func calcG(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(lOpd.Number > rOpd.Number))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) == 1))
	}
	if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(true))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(false))
	}
	return nil
}

// calcGe evaluate greater than or equal arithmetic operations.
func calcGe(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Type == ArgNumber && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(lOpd.Number >= rOpd.Number))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(strings.Compare(lOpd.Value(), rOpd.Value()) != -1))
	}
	if rOpd.Type == ArgNumber && lOpd.Type == ArgString {
		opdStack.Push(newBoolFormulaArg(true))
	}
	if rOpd.Type == ArgString && lOpd.Type == ArgNumber {
		opdStack.Push(newBoolFormulaArg(false))
	}
	return nil
}

// calcSplice evaluate splice '&' operations.
func calcSplice(rOpd, lOpd formulaArg, opdStack *Stack) error {
	opdStack.Push(newStringFormulaArg(lOpd.Value() + rOpd.Value()))
	return nil
}

// calcAdd evaluate addition arithmetic operations.
func calcAdd(rOpd, lOpd formulaArg, opdStack *Stack) error {
	lOpdVal := lOpd.ToNumber()
	if lOpdVal.Type != ArgNumber {
		return errors.New(lOpdVal.Value())
	}
	rOpdVal := rOpd.ToNumber()
	if rOpdVal.Type != ArgNumber {
		return errors.New(rOpdVal.Value())
	}
	opdStack.Push(newNumberFormulaArg(lOpdVal.Number + rOpdVal.Number))
	return nil
}

// calcSubtract evaluate subtraction arithmetic operations.
func calcSubtract(rOpd, lOpd formulaArg, opdStack *Stack) error {
	if rOpd.Value() == "" {
		rOpd = newNumberFormulaArg(0)
	}
	if lOpd.Value() == "" {
		lOpd = newNumberFormulaArg(0)
	}
	lOpdVal := lOpd.ToNumber()
	if lOpdVal.Type != ArgNumber {
		return errors.New(lOpdVal.Value())
	}
	rOpdVal := rOpd.ToNumber()
	if rOpdVal.Type != ArgNumber {
		return errors.New(rOpdVal.Value())
	}
	opdStack.Push(newNumberFormulaArg(lOpdVal.Number - rOpdVal.Number))
	return nil
}

// calcMultiply evaluate multiplication arithmetic operations.
func calcMultiply(rOpd, lOpd formulaArg, opdStack *Stack) error {
	lOpdVal := lOpd.ToNumber()
	if lOpdVal.Type != ArgNumber {
		return errors.New(lOpdVal.Value())
	}
	rOpdVal := rOpd.ToNumber()
	if rOpdVal.Type != ArgNumber {
		return errors.New(rOpdVal.Value())
	}
	opdStack.Push(newNumberFormulaArg(lOpdVal.Number * rOpdVal.Number))
	return nil
}

// calcDiv evaluate division arithmetic operations.
func calcDiv(rOpd, lOpd formulaArg, opdStack *Stack) error {
	lOpdVal := lOpd.ToNumber()
	if lOpdVal.Type != ArgNumber {
		return errors.New(lOpdVal.Value())
	}
	rOpdVal := rOpd.ToNumber()
	if rOpdVal.Type != ArgNumber {
		return errors.New(rOpdVal.Value())
	}
	if rOpdVal.Number == 0 {
		return errors.New(formulaErrorDIV)
	}
	opdStack.Push(newNumberFormulaArg(lOpdVal.Number / rOpdVal.Number))
	return nil
}

// calculate evaluate basic arithmetic operations.
func calculate(opdStack *Stack, opt efp.Token) error {
	if opt.TValue == "-" && opt.TType == efp.TokenTypeOperatorPrefix {
		if opdStack.Len() < 1 {
			return ErrInvalidFormula
		}
		opd := opdStack.Pop().(formulaArg)
		opdStack.Push(newNumberFormulaArg(0 - opd.ToNumber().Number))
	}
	if opt.TValue == "-" && opt.TType == efp.TokenTypeOperatorInfix {
		if opdStack.Len() < 2 {
			return ErrInvalidFormula
		}
		rOpd := opdStack.Pop().(formulaArg)
		lOpd := opdStack.Pop().(formulaArg)
		if err := calcSubtract(rOpd, lOpd, opdStack); err != nil {
			return err
		}
	}
	tokenCalcFunc := map[string]func(rOpd, lOpd formulaArg, opdStack *Stack) error{
		"^":  calcPow,
		"*":  calcMultiply,
		"/":  calcDiv,
		"+":  calcAdd,
		"=":  calcEq,
		"<>": calcNEq,
		"<":  calcL,
		"<=": calcLe,
		">":  calcG,
		">=": calcGe,
		"&":  calcSplice,
	}
	if fn, ok := tokenCalcFunc[opt.TValue]; ok {
		if opdStack.Len() < 2 {
			return ErrInvalidFormula
		}
		rOpd := opdStack.Pop().(formulaArg)
		lOpd := opdStack.Pop().(formulaArg)
		if opt.TValue != "&" {
			if rOpd.Value() == "" {
				rOpd = newNumberFormulaArg(0)
			}
			if lOpd.Value() == "" {
				lOpd = newNumberFormulaArg(0)
			}
		}
		if rOpd.Type == ArgError {
			return errors.New(rOpd.Value())
		}
		if lOpd.Type == ArgError {
			return errors.New(lOpd.Value())
		}
		return fn(rOpd, lOpd, opdStack)
	}
	return nil
}

// parseOperatorPrefixToken parse operator prefix token.
func (f *File) parseOperatorPrefixToken(optStack, opdStack *Stack, token efp.Token) (err error) {
	if optStack.Len() == 0 {
		optStack.Push(token)
		return
	}
	tokenPriority := getPriority(token)
	topOpt := optStack.Peek().(efp.Token)
	topOptPriority := getPriority(topOpt)
	if topOpt.TValue == "-" && topOpt.TType == efp.TokenTypeOperatorPrefix && token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix {
		optStack.Pop()
		return
	}
	if tokenPriority > topOptPriority {
		optStack.Push(token)
		return
	}
	for tokenPriority <= topOptPriority {
		optStack.Pop()
		if err = calculate(opdStack, topOpt); err != nil {
			return
		}
		if optStack.Len() > 0 {
			topOpt = optStack.Peek().(efp.Token)
			topOptPriority = getPriority(topOpt)
			continue
		}
		break
	}
	optStack.Push(token)
	return
}

// isFunctionStartToken determine if the token is function start.
func isFunctionStartToken(token efp.Token) bool {
	return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStart
}

// isFunctionStopToken determine if the token is function stop.
func isFunctionStopToken(token efp.Token) bool {
	return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStop
}

// isBeginParenthesesToken determine if the token is begin parentheses: (.
func isBeginParenthesesToken(token efp.Token) bool {
	return token.TType == efp.TokenTypeSubexpression && token.TSubType == efp.TokenSubTypeStart
}

// isEndParenthesesToken determine if the token is end parentheses: ).
func isEndParenthesesToken(token efp.Token) bool {
	return token.TType == efp.TokenTypeSubexpression && token.TSubType == efp.TokenSubTypeStop
}

// isOperatorPrefixToken determine if the token is parse operator prefix
// token.
func isOperatorPrefixToken(token efp.Token) bool {
	_, ok := tokenPriority[token.TValue]
	return (token.TValue == "-" && token.TType == efp.TokenTypeOperatorPrefix) || (ok && token.TType == efp.TokenTypeOperatorInfix)
}

// isOperand determine if the token is parse operand.
func isOperand(token efp.Token) bool {
	return token.TType == efp.TokenTypeOperand && (token.TSubType == efp.TokenSubTypeNumber || token.TSubType == efp.TokenSubTypeText || token.TSubType == efp.TokenSubTypeLogical)
}

// tokenToFormulaArg create a formula argument by given token.
func tokenToFormulaArg(token efp.Token) formulaArg {
	switch token.TSubType {
	case efp.TokenSubTypeLogical:
		return newBoolFormulaArg(strings.EqualFold(token.TValue, "TRUE"))
	case efp.TokenSubTypeNumber:
		num, _ := strconv.ParseFloat(token.TValue, 64)
		return newNumberFormulaArg(num)
	default:
		return newStringFormulaArg(token.TValue)
	}
}

// formulaArgToToken create a token by given formula argument.
func formulaArgToToken(arg formulaArg) efp.Token {
	switch arg.Type {
	case ArgNumber:
		if arg.Boolean {
			return efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeLogical}
		}
		return efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}
	default:
		return efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeText}
	}
}

// parseToken parse basic arithmetic operator priority and evaluate based on
// operators and operands.
func (f *File) parseToken(ctx *calcContext, sheet string, token efp.Token, opdStack, optStack *Stack) error {
	// parse reference: must reference at here
	if token.TSubType == efp.TokenSubTypeRange {
		refTo := f.getDefinedNameRefTo(token.TValue, sheet)
		if refTo != "" {
			token.TValue = refTo
		}
		result, err := f.parseReference(ctx, sheet, token.TValue)
		if err != nil {
			return errors.New(formulaErrorNAME)
		}
		token = formulaArgToToken(result)
	}
	if isOperatorPrefixToken(token) {
		if err := f.parseOperatorPrefixToken(optStack, opdStack, token); err != nil {
			return err
		}
	}
	if isBeginParenthesesToken(token) { // (
		optStack.Push(token)
	}
	if isEndParenthesesToken(token) { // )
		for !isBeginParenthesesToken(optStack.Peek().(efp.Token)) { // != (
			topOpt := optStack.Peek().(efp.Token)
			if err := calculate(opdStack, topOpt); err != nil {
				return err
			}
			optStack.Pop()
		}
		optStack.Pop()
	}
	if token.TType == efp.TokenTypeOperatorPostfix && !opdStack.Empty() {
		topOpd := opdStack.Pop().(formulaArg)
		opdStack.Push(newNumberFormulaArg(topOpd.Number / 100))
	}
	// opd
	if isOperand(token) {
		opdStack.Push(tokenToFormulaArg(token))
	}
	return nil
}

// parseRef parse reference for a cell, column name or row number.
func parseRef(ref string) (cellRef, bool, bool, error) {
	var (
		err, colErr, rowErr error
		cr                  cellRef
		cell                = ref
		tokens              = strings.Split(ref, "!")
	)
	if len(tokens) == 2 { // have a worksheet
		cr.Sheet, cell = strings.TrimSuffix(strings.TrimPrefix(tokens[0], "'"), "'"), tokens[1]
	}
	if cr.Col, cr.Row, err = CellNameToCoordinates(cell); err != nil {
		if cr.Col, colErr = ColumnNameToNumber(cell); colErr == nil { // cast to column
			return cr, true, false, nil
		}
		if cr.Row, rowErr = strconv.Atoi(cell); rowErr == nil { // cast to row
			if cr.Row < 1 || cr.Row > TotalRows {
				return cr, false, false, err
			}
			return cr, false, true, nil
		}
		return cr, false, false, err
	}
	return cr, false, false, err
}

// prepareCellRange checking and convert cell reference to a cell range.
func (cr *cellRange) prepareCellRange(col, row bool, cellRef cellRef) error {
	if col {
		cellRef.Row = TotalRows
	}
	if row {
		cellRef.Col = MaxColumns
	}
	if cellRef.Sheet == "" {
		cellRef.Sheet = cr.From.Sheet
	}
	if cr.From.Sheet != cellRef.Sheet || cr.To.Sheet != cellRef.Sheet {
		return errors.New("invalid reference")
	}
	if cr.From.Col > cellRef.Col {
		cr.From.Col = cellRef.Col
	}
	if cr.From.Row > cellRef.Row {
		cr.From.Row = cellRef.Row
	}
	if cr.To.Col < cellRef.Col {
		cr.To.Col = cellRef.Col
	}
	if cr.To.Row < cellRef.Row {
		cr.To.Row = cellRef.Row
	}
	return nil
}

// parseReference parse reference and extract values by given reference
// characters and default sheet name.
func (f *File) parseReference(ctx *calcContext, sheet, reference string) (formulaArg, error) {
	reference = strings.ReplaceAll(reference, "$", "")
	ranges, cellRanges, cellRefs := strings.Split(reference, ":"), list.New(), list.New()
	if len(ranges) > 1 {
		var cr cellRange
		for i, ref := range ranges {
			cellRef, col, row, err := parseRef(ref)
			if err != nil {
				return newErrorFormulaArg(formulaErrorNAME, "invalid reference"), errors.New("invalid reference")
			}
			if i == 0 {
				if col {
					cellRef.Row = 1
				}
				if row {
					cellRef.Col = 1
				}
				if cellRef.Sheet == "" {
					cellRef.Sheet = sheet
				}
				cr.From, cr.To = cellRef, cellRef
				continue
			}
			if err := cr.prepareCellRange(col, row, cellRef); err != nil {
				return newErrorFormulaArg(formulaErrorNAME, err.Error()), err
			}
		}
		cellRanges.PushBack(cr)
		return f.rangeResolver(ctx, cellRefs, cellRanges)
	}
	cellRef, _, _, err := parseRef(reference)
	if err != nil {
		return newErrorFormulaArg(formulaErrorNAME, "invalid reference"), errors.New("invalid reference")
	}
	if cellRef.Sheet == "" {
		cellRef.Sheet = sheet
	}
	cellRefs.PushBack(cellRef)
	return f.rangeResolver(ctx, cellRefs, cellRanges)
}

// prepareValueRange prepare value range.
func prepareValueRange(cr cellRange, valueRange []int) {
	if cr.From.Row < valueRange[0] || valueRange[0] == 0 {
		valueRange[0] = cr.From.Row
	}
	if cr.From.Col < valueRange[2] || valueRange[2] == 0 {
		valueRange[2] = cr.From.Col
	}
	if cr.To.Row > valueRange[1] || valueRange[1] == 0 {
		valueRange[1] = cr.To.Row
	}
	if cr.To.Col > valueRange[3] || valueRange[3] == 0 {
		valueRange[3] = cr.To.Col
	}
}

// prepareValueRef prepare value reference.
func prepareValueRef(cr cellRef, valueRange []int) {
	if cr.Row < valueRange[0] || valueRange[0] == 0 {
		valueRange[0] = cr.Row
	}
	if cr.Col < valueRange[2] || valueRange[2] == 0 {
		valueRange[2] = cr.Col
	}
	if cr.Row > valueRange[1] || valueRange[1] == 0 {
		valueRange[1] = cr.Row
	}
	if cr.Col > valueRange[3] || valueRange[3] == 0 {
		valueRange[3] = cr.Col
	}
}

// cellResolver calc cell value by given worksheet name, cell reference and context.
func (f *File) cellResolver(ctx *calcContext, sheet, cell string) (formulaArg, error) {
	var (
		arg   formulaArg
		value string
		err   error
	)
	ref := sheet + "!" + cell
	if cached, ok := f.formulaArgCache.Load(ref); ok {
		return cached.(formulaArg), err
	}

	if formula, _ := f.getCellFormula(sheet, cell, true); len(formula) != 0 {
		ctx.mu.Lock()
		if ctx.entry != ref {
			if ctx.iterations[ref] <= f.options.MaxCalcIterations {
				ctx.iterations[ref]++
				ctx.mu.Unlock()
				arg, _ = f.calcCellValue(ctx, sheet, cell)
				ctx.iterationsCache[ref] = arg
				f.formulaArgCache.Store(ref, arg)
				return arg, nil
			}
			ctx.mu.Unlock()
			return ctx.iterationsCache[ref], nil
		}
		ctx.mu.Unlock()
	}
	if value, err = f.GetCellValue(sheet, cell, Options{RawCellValue: true}); err != nil {
		return arg, err
	}
	arg = newStringFormulaArg(value)
	cellType, _ := f.GetCellType(sheet, cell)
	switch cellType {
	case CellTypeBool:
		arg = arg.ToBool()
	case CellTypeNumber, CellTypeUnset:
		if arg.Value() == "" {
			arg = newEmptyFormulaArg()
		} else {
			arg = arg.ToNumber()
		}
	case CellTypeInlineString, CellTypeSharedString:
	case CellTypeFormula:
		if value == "" {
			arg = newEmptyFormulaArg()
		}
	case CellTypeDate:
		if value, err = f.GetCellValue(sheet, cell); err == nil {
			if num := newStringFormulaArg(value).ToNumber(); num.Type == ArgNumber {
				arg = num
			}
		}
	default:
		arg = newErrorFormulaArg(value, value)
	}
	f.formulaArgCache.Store(ref, arg)
	return arg, err
}

// rangeResolver extract value as string from given reference and range list.
// This function will not ignore the empty cell. For example, A1:A2:A2:B3 will
// be reference A1:B3.
func (f *File) rangeResolver(ctx *calcContext, cellRefs, cellRanges *list.List) (arg formulaArg, err error) {
	arg.cellRefs, arg.cellRanges = cellRefs, cellRanges
	// value range order: from row, to row, from column, to column
	valueRange := []int{0, 0, 0, 0}
	var sheet string
	// prepare value range
	for temp := cellRanges.Front(); temp != nil; temp = temp.Next() {
		cr := temp.Value.(cellRange)
		rng := []int{cr.From.Col, cr.From.Row, cr.To.Col, cr.To.Row}
		_ = sortCoordinates(rng)
		cr.From.Col, cr.From.Row, cr.To.Col, cr.To.Row = rng[0], rng[1], rng[2], rng[3]
		prepareValueRange(cr, valueRange)
		if cr.From.Sheet != "" {
			sheet = cr.From.Sheet
		}
	}
	for temp := cellRefs.Front(); temp != nil; temp = temp.Next() {
		cr := temp.Value.(cellRef)
		if cr.Sheet != "" {
			sheet = cr.Sheet
		}
		prepareValueRef(cr, valueRange)
	}
	// extract value from ranges
	if cellRanges.Len() > 0 {
		arg.Type = ArgMatrix

		var ws *xlsxWorksheet
		ws, err = f.workSheetReader(sheet)
		if err != nil {
			return
		}

		// Detect whole column/row reference, limit to actual data range
		if valueRange[1] == TotalRows {
			actualMaxRow := 0
			for _, rowData := range ws.SheetData.Row {
				if rowData.R > actualMaxRow {
					actualMaxRow = rowData.R
				}
			}
			if actualMaxRow > 0 && actualMaxRow < TotalRows {
				valueRange[1] = actualMaxRow
			}
		}
		if valueRange[3] == MaxColumns {
			actualMaxCol := 0
			for _, rowData := range ws.SheetData.Row {
				for _, cell := range rowData.C {
					col, _, err := CellNameToCoordinates(cell.R)
					if err == nil && col > actualMaxCol {
						actualMaxCol = col
					}
				}
			}
			if actualMaxCol > 0 && actualMaxCol < MaxColumns {
				valueRange[3] = actualMaxCol
			}
		}

		for row := valueRange[0]; row <= valueRange[1]; row++ {
			colMax := 0
			if 0 < row && row <= len(ws.SheetData.Row) {
				rowData := &ws.SheetData.Row[row-1]
				colMax = min(valueRange[3], len(rowData.C))
			}
			var matrixRow []formulaArg
			for col := valueRange[2]; col <= valueRange[3]; col++ {
				value := newEmptyFormulaArg()
				if col <= colMax {
					var cell string
					if cell, err = CoordinatesToCellName(col, row); err != nil {
						return
					}
					if value, err = f.cellResolver(ctx, sheet, cell); err != nil {
						return
					}
				}
				matrixRow = append(matrixRow, value)
			}
			arg.Matrix = append(arg.Matrix, matrixRow)
		}
		return
	}
	// extract value from references
	for temp := cellRefs.Front(); temp != nil; temp = temp.Next() {
		cr := temp.Value.(cellRef)
		var cell string
		if cell, err = CoordinatesToCellName(cr.Col, cr.Row); err != nil {
			return
		}
		if arg, err = f.cellResolver(ctx, cr.Sheet, cell); err != nil {
			return
		}
		arg.cellRefs, arg.cellRanges = cellRefs, cellRanges
	}
	return
}

// callFuncByName calls the no error or only error return function with
// reflect by given receiver, name and parameters.
func callFuncByName(receiver interface{}, name string, params []reflect.Value) (arg formulaArg) {
	function := reflect.ValueOf(receiver).MethodByName(name)
	if function.IsValid() {
		rt := function.Call(params)
		if len(rt) == 0 {
			return
		}
		arg = rt[0].Interface().(formulaArg)
		return
	}
	return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("not support %s function", name))
}

// formulaCriteriaParser parse formula criteria.
func formulaCriteriaParser(exp formulaArg) *formulaCriteria {
	prepareValue := func(cond string) (expected float64, err error) {
		percentile := 1.0
		if strings.HasSuffix(cond, "%") {
			cond = strings.TrimSuffix(cond, "%")
			percentile /= 100
		}
		if expected, err = strconv.ParseFloat(cond, 64); err != nil {
			return
		}
		expected *= percentile
		return
	}
	fc, val := &formulaCriteria{}, exp.Value()
	if val == "" {
		return fc
	}
	for i, re := range formulaFormats {
		if match := re.FindStringSubmatch(val); len(match) > 1 {
			fc.Condition = newStringFormulaArg(match[1])
			if num, err := prepareValue(match[1]); err == nil {
				fc.Condition = newNumberFormulaArg(num)
			}
			fc.Type = formulaCriterias[i]
			return fc
		}
	}
	hasWildcard := false
	pattern := wildcardTokenRE.ReplaceAllStringFunc(val, func(m string) string {
		hasWildcard = hasWildcard || wildcardBareTokens[m]
		if r, ok := wildcardPatternMap[m]; ok {
			return r
		}
		return regexp.QuoteMeta(m)
	})
	if hasWildcard {
		fc.Type, fc.Condition = criteriaRegexp, newStringFormulaArg("(?i)^"+pattern+"$")
		return fc
	}
	fc.Type, fc.Condition = criteriaEq, newStringFormulaArg(
		strings.NewReplacer("~~", "~", "~*", "*", "~?", "?").Replace(val),
	)
	if num := fc.Condition.ToNumber(); num.Type == ArgNumber {
		fc.Condition = num
	}
	return fc
}

// formulaCriteriaEval evaluate formula criteria expression.
func formulaCriteriaEval(val formulaArg, criteria *formulaCriteria) (result bool, err error) {
	s := NewStack()
	tokenCalcFunc := map[byte]func(rOpd, lOpd formulaArg, opdStack *Stack) error{
		criteriaEq: calcEq,
		criteriaNe: calcNEq,
		criteriaL:  calcL,
		criteriaLe: calcLe,
		criteriaG:  calcG,
		criteriaGe: calcGe,
	}
	switch criteria.Type {
	case criteriaEq, criteriaLe, criteriaGe, criteriaNe, criteriaL, criteriaG:
		if fn, ok := tokenCalcFunc[criteria.Type]; ok {
			if _ = fn(criteria.Condition, val, s); s.Len() > 0 {
				return s.Pop().(formulaArg).Number == 1, err
			}
		}
	case criteriaRegexp:
		pattern := criteria.Condition.Value()
		if !strings.HasPrefix(pattern, "^") {
			pattern = "^" + pattern
		}
		if !strings.HasSuffix(pattern, "$") {
			pattern = pattern + "$"
		}
		return regexp.MatchString(pattern, val.Value())
	}
	return
}

// Engineering Functions

// BESSELI function the modified Bessel function, which is equivalent to the
// Bessel function evaluated for purely imaginary arguments. The syntax of
// the Besseli function is:
//
//	BESSELI(x,n)
func (fn *formulaFuncs) BESSELI(argsList *list.List) formulaArg {
	if argsList.Len() != 2 {
		return newErrorFormulaArg(formulaErrorVALUE, "BESSELI requires 2 numeric arguments")
	}
	return fn.bassel(argsList, true)
}

// BESSELJ function returns the Bessel function, Jn(x), for a specified order
// and value of x. The syntax of the function is:
//
//	BESSELJ(x,n)
func (fn *formulaFuncs) BESSELJ(argsList *list.List) formulaArg {
	if argsList.Len() != 2 {
		return newErrorFormulaArg(formulaErrorVALUE, "BESSELJ requires 2 numeric arguments")
	}
	return fn.bassel(argsList, false)
}

// bassel is an implementation of the formula functions BESSELI and BESSELJ.
func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) formulaArg {
	x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
	if x.Type != ArgNumber {
		return x
	}
	if n.Type != ArgNumber {
		return n
	}
	maxVal, x1 := 100, x.Number*0.5
	x2 := x1 * x1
	x1 = math.Pow(x1, n.Number)
	n1, n2, n3, n4, add := fact(n.Number), 1.0, 0.0, n.Number, false
	result := x1 / n1
	t := result * 0.9
	for result != t && maxVal != 0 {
		x1 *= x2
		n3++
		n1 *= n3
		n4++
		n2 *= n4
		t = result
		r := x1 / n1 / n2
		if modfied || add {
			result += r
		} else {
			result -= r
		}
		maxVal--
		add = !add
	}
	return newNumberFormulaArg(result)
}

// BESSELK function calculates the modified Bessel functions, Kn(x), which are
// also known as the hyperbolic Bessel Functions. These are the equivalent of
// the Bessel functions, evaluated for purely imaginary arguments. The syntax
// of the function is:
//
//	BESSELK(x,n)
func (fn *formulaFuncs) BESSELK(argsList *list.List) formulaArg {
	if argsList.Len() != 2 {
		return newErrorFormulaArg(formulaErrorVALUE, "BESSELK requires 2 numeric arguments")
	}
	x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
	if x.Type != ArgNumber {
		return x
	}
	if n.Type != ArgNumber {
		return n
	}
	if x.Number <= 0 || n.Number < 0 {
		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
	}
	var result float64
	switch math.Floor(n.Number) {
	case 0:
		result = fn.besselK0(x)
	case 1:
		result = fn.besselK1(x)
	default:
		result = fn.besselK2(x, n)
	}
	return newNumberFormulaArg(result)
}

// besselK0 is an implementation of the formula function BESSELK.
func (fn *formulaFuncs) besselK0(x formulaArg) float64 {
	var y float64
	if x.Number <= 2 {
		n2 := x.Number * 0.5
		y = n2 * n2
		args := list.New()
		args.PushBack(x)
		args.PushBack(newNumberFormulaArg(0))
		return -math.Log(n2)*fn.BESSELI(args).Number +
			(-0.57721566 + y*(0.42278420+y*(0.23069756+y*(0.3488590e-1+y*(0.262698e-2+y*
				(0.10750e-3+y*0.74e-5))))))
	}
	y = 2 / x.Number
	return math.Exp(-x.Number) / math.Sqrt(x.Number) *
		(1.25331414 + y*(-0.7832358e-1+y*(0.2189568e-1+y*(-0.1062446e-1+y*
			(0.587872e-2+y*(-0.251540e-2+y*0.53208e-3))))))
}

// besselK1 is an implementation of the formula function BESSELK.
func (fn *formulaFuncs) besselK1(x formulaArg) float64 {
	var n2, y float64
	if x.Number <= 2 {
		n2 = x.Number * 0.5
		y = n2 * n2
		args := list.New()
		args.PushBack(x)
		args.PushBack(newNumberFormulaArg(1))
		return math.Log(n2)*fn.BESSELI(args).Number +
			(1+y*(0.15443144+y*(-0.67278579+y*(-0.18156897+y*(-0.1919402e-1+y*(-0.110404e-2+y*(-0.4686e-4)))))))/x.Number
	}
	y = 2 / x.Number
	return math.Exp(-x.Number) / math.Sqrt(x.Number) *
		(1.25331414 + y*(0.23498619+y*(-0.3655620e-1+y*(0.1504268e-1+y*(-0.780353e-2+y*
			(0.325614e-2+y*(-0.68245e-3)))))))
}

// besselK2 is an implementation of the formula function BESSELK.
func (fn *formulaFuncs) besselK2(x, n formulaArg) float64 {
	tox, bkm, bk, bkp := 2/x.Number, fn.besselK0(x), fn.besselK1(x), 0.0
	for i := 1.0; i < n.Number; i++ {
		bkp = math.FMA(i*tox, bk, bkm)
		bkm = bk
		bk = bkp
	}
	return bk
}

// BESSELY function returns the Bessel function, Yn(x), (also known as the
// Weber function or the Neumann function), for a specified order and value
// of x. The syntax of the function is:
//
//	BESSELY(x,n)
func (fn *formulaFuncs) BESSELY(argsList *list.List) formulaArg {
	if argsList.Len() != 2 {
		return newErrorFormulaArg(formulaErrorVALUE, "BESSELY requires 2 numeric arguments")
	}
	x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
	if x.Type != ArgNumber {
		return x
	}
	if n.Type != ArgNumber {
		return n
	}
	if x.Number <= 0 || n.Number < 0 {
		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
	}
	var result float64
	switch math.Floor(n.Number) {
	case 0:
		result = fn.besselY0(x)
	case 1:
		result = fn.besselY1(x)
	default:
		result = fn.besselY2(x, n)
	}
	return newNumberFormulaArg(result)
}

// besselY0 is an implementation of the formula function BESSELY.
func (fn *formulaFuncs) besselY0(x formulaArg) float64 {
	var y float64
	if x.Number < 8 {
		y = x.Number * x.Number
		f1 := -2957821389.0 + y*(7062834065.0+y*(-512359803.6+y*(10879881.29+y*
			(-86327.92757+y*228.4622733))))
		f2 := 40076544269.0 + y*(745249964.8+y*(7189466.438+y*
			(47447.26470+y*(226.1030244+y))))
		args := list.New()
		args.PushBack(x)
		args.PushBack(newNumberFormulaArg(0))
		return f1/f2 + 0.636619772*fn.BESSELJ(args).Number*math.Log(x.Number)
	}
	z := 8.0 / x.Number
	y = z * z
	xx := x.Number - 0.785398164
	f1 := 1 + y*(-0.1098628627e-2+y*(0.2734510407e-4+y*(-0.2073370639e-5+y*0.2093887211e-6)))
	f2 := -0.1562499995e-1 + y*(0.1430488765e-3+y*(-0.6911147651e-5+y*(0.7621095161e-6+y*
		(-0.934945152e-7))))
	return math.Sqrt(0.636619772/x.Number) * (math.Sin(xx)*f1 + z*math.Cos(xx)*f2)
}

// besselY1 is an implementation of the formula function BESSELY.
func (fn *formulaFuncs) besselY1(x formulaArg) float64 {
	if x.Number < 8 {
		y := x.Number * x.Number
		f1 := x.Number * (-0.4900604943e13 + y*(0.1275274390e13+y*(-0.5153438139e11+y*
			(0.7349264551e9+y*(-0.4237922726e7+y*0.8511937935e4)))))
		f2 := 0.2499580570e14 + y*(0.4244419664e12+y*(0.3733650367e10+y*(0.2245904002e8+y*
			(0.1020426050e6+y*(0.3549632885e3+y)))))
		args := list.New()
		args.PushBack(x)
		args.PushBack(newNumberFormulaArg(1))
		return f1/f2 + 0.636619772*(fn.BESSELJ(args).Number*math.Log(x.Number)-1/x.Number)
	}
	return math.Sqrt(0.636619772/x.Number) * math.Sin(x.Number-2.356194491)
}

// besselY2 is an implementation of the formula function BESSELY.
func (fn *formulaFuncs) besselY2(x, n formulaArg) float64 {
	tox, bym, by, byp := 2/x.Number, fn.besselY0(x), fn.besselY1(x), 0.0
	for i := 1.0; i < n.Number; i++ {
		byp = math.FMA(i*tox, by, -bym)
		bym = by
		by = byp
	}
	return by
}

// BIN2DEC function converts a Binary (a base-2 number) into a decimal number.
// The syntax of the function is:
//
//	BIN2DEC(number)
func (fn *formulaFuncs) BIN2DEC(argsList *list.List) formulaArg {
	if argsList.Len() != 1 {
		return newErrorFormulaArg(formulaErrorVALUE, "BIN2DEC requires 1 numeric argument")
	}
	token := argsList.Front().Value.(formulaArg)
	number := token.ToNumber()
	if number.Type != ArgNumber {
		return newErrorFormulaArg(formulaErrorVALUE, number.Error)
	}
	return fn.bin2dec(token.Value())
}

// BIN2HEX function converts a Binary (Base 2) number into a Hexadecimal
// (Base 16) number. The syntax of the function is:
//
//	BIN2HEX(number,[places])
func (fn *formulaFuncs) BIN2HEX(argsList *list.List) formulaArg {
	if argsList.Len() < 1 {
		return newErrorFormulaArg(formulaErrorVALUE, "BIN2HEX requires at least 1 argument")
	}
	if argsList.Len() > 2 {
		return newErrorFormulaArg(formulaErrorVALUE, "BIN2HEX allows at most 2 arguments")
	}
	token := argsList.Front().Value.(formulaArg)
	number := token.ToNumber()
	if number.Type != ArgNumber {
		return newErrorFormulaArg(formulaErrorVALUE, number.Error)
	}
	decimal, newList := fn.bin2dec(token.Value()), list.New()
	if decimal.Type != ArgNumber {
		return decimal
	}
	newList.PushBack(decimal)
	if argsList.Len() == 2 {
		newList.PushBack(argsList.Back().Value.(formulaArg))
	}
	return fn.dec2x("BIN2HEX", newList)
}

// BIN2OCT function converts a Binary (Base 2) number into an Octal (Base 8)
// number. The syntax of the function is:
//
//	BIN2OCT(number,[places])
func (fn *formulaFuncs) BIN2OCT(argsList *list.List) formulaArg {
	if argsList.Len() < 1 {
		return newErrorFormulaArg(formulaErrorVALUE, "BIN2OCT requires at least 1 argument")
	}
	if argsList.Len() > 2 {
		return newErrorFormulaArg(formulaErrorVALUE, "BIN2OCT allows at most 2 arguments")
	}
	token := argsList.Front().Value.(formulaArg)
	number := token.ToNumber()
	if number.Type != ArgNumber {
		return newErrorFormulaArg(formulaErrorVALUE, number.Error)
	}
	decimal, newList := fn.bin2dec(token.Value()), list.New()
	if decimal.Type != ArgNumber {
		return decimal
	}
	newList.PushBack(decimal)
	if argsList.Len() == 2 {
		newList.PushBack(argsList.Back().Value.(formulaArg))
	}
	return fn.dec2x("BIN2OCT", newList)
}

// bin2dec is an implementation of the formula function BIN2DEC.
func (fn *formulaFuncs) bin2dec(number string) formulaArg {
	decimal, length := 0.0, len(number)
	for i := length; i > 0; i-- {
		s := string(number[length-i])
		if i == 10 && s == "1" {
			decimal += math.Pow(-2.0, float64(i-1))
			continue
		}
		if s == "1" {
			decimal += math.Pow(2.0, float64(i-1))
			continue
		}
		if s != "0" {
			return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
		}
	}
	return newNumberFormulaArg(decimal)
}

// BITAND function returns the bitwise 'AND' for two supplied integers. The
// syntax of the function is:
//
//	BITAND(number1,number2)
func (fn *formulaFuncs) BITAND(argsList *list.List) formulaArg {
	return fn.bitwise("BITAND", argsList)
}

// BITLSHIFT function returns a supplied integer, shifted left by a specified
// number of bits. The syntax of the function is:
//
//	BITLSHIFT(number1,shift_amount)
func (fn *formulaFuncs) BITLSHIFT(argsList *list.List) formulaArg {
	return fn.bitwise("BITLSHIFT", argsList)
}

// BITOR function returns the bitwise 'OR' for two supplied integers. The
// syntax of the function is:
//
//	BITOR(number1,number2)
func (fn *formulaFuncs) BITOR(argsList *list.List) formulaArg {
	return fn.bitwise("BITOR", argsList)
}

// BITRSHIFT function returns a supplied integer, shifted right by a specified
// number of bits. The syntax of the function is:
//
//	BITRSHIFT(number1,shift_amount)
func (fn *formulaFuncs) BITRSHIFT(argsList *list.List) formulaArg {
	return fn.bitwise("BITRSHIFT", argsList)
}

// BITXOR function returns the bitwise 'XOR' (exclusive 'OR') for two supplied
// integers. The syntax of the function is:
//
//	BITXOR(number1,number2)
func (fn *formulaFuncs) BITXOR(argsList *list.List) formulaArg {
	return fn.bitwise("BITXOR", argsList)
}

// bitwise is an implementation of the formula functions BITAND, BITLSHIFT,
// BITOR, BITRSHIFT and BITXOR.
func (fn *formulaFuncs) bitwise(name string, argsList *list.List) formulaArg {
	if argsList.Len() != 2 {
		return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 2 numeric arguments", name))
	}
	num1, num2 := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
	if num1.Type != ArgNumber || num2.Type != ArgNumber {
		return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
	}
	maxVal := math.Pow(2, 48) - 1
	if num1.Number < 0 || num1.Number > maxVal || num2.N
Download .txt
gitextract_jqjalinp/

├── .github/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   └── feature_request.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── SECURITY.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── codeql-analysis.yml
│       └── go.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_zh.md
├── adjust.go
├── adjust_test.go
├── calc.go
├── calc_test.go
├── calcchain.go
├── calcchain_test.go
├── cell.go
├── cell_test.go
├── chart.go
├── chart_test.go
├── col.go
├── col_test.go
├── crypt.go
├── crypt_test.go
├── datavalidation.go
├── datavalidation_test.go
├── date.go
├── date_test.go
├── docProps.go
├── docProps_test.go
├── drawing.go
├── drawing_test.go
├── errors.go
├── errors_test.go
├── excelize.go
├── excelize_test.go
├── file.go
├── file_test.go
├── go.mod
├── go.sum
├── hsl.go
├── lib.go
├── lib_test.go
├── merge.go
├── merge_test.go
├── numfmt.go
├── numfmt_test.go
├── picture.go
├── picture_test.go
├── pivotTable.go
├── pivotTable_test.go
├── rows.go
├── rows_test.go
├── shape.go
├── shape_test.go
├── sheet.go
├── sheet_test.go
├── sheetpr.go
├── sheetpr_test.go
├── sheetview.go
├── sheetview_test.go
├── slicer.go
├── slicer_test.go
├── sparkline.go
├── sparkline_test.go
├── stream.go
├── stream_test.go
├── styles.go
├── styles_test.go
├── table.go
├── table_test.go
├── templates.go
├── test/
│   ├── BadWorkbook.xlsx
│   ├── Book1.xlsx
│   ├── CalcChain.xlsx
│   ├── MergeCell.xlsx
│   ├── OverflowNumericCell.xlsx
│   ├── SharedStrings.xlsx
│   ├── encryptAES.xlsx
│   ├── encryptSHA1.xlsx
│   └── images/
│       ├── excel.emf
│       ├── excel.emz
│       ├── excel.tif
│       ├── excel.wmf
│       └── excel.wmz
├── vml.go
├── vmlDrawing.go
├── vml_test.go
├── workbook.go
├── workbook_test.go
├── xmlApp.go
├── xmlCalcChain.go
├── xmlChart.go
├── xmlChartSheet.go
├── xmlComments.go
├── xmlContentTypes.go
├── xmlCore.go
├── xmlCustom.go
├── xmlDecodeDrawing.go
├── xmlDrawing.go
├── xmlMetaData.go
├── xmlPivotCache.go
├── xmlPivotTable.go
├── xmlSharedStrings.go
├── xmlSlicers.go
├── xmlStyles.go
├── xmlTable.go
├── xmlTheme.go
├── xmlWorkbook.go
└── xmlWorksheet.go
Download .txt
Showing preview only (287K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3163 symbols across 85 files)

FILE: adjust.go
  type adjustDirection (line 25) | type adjustDirection
  constant columns (line 28) | columns adjustDirection = false
  constant rows (line 29) | rows    adjustDirection = true
  method adjustHelper (line 73) | func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offs...
  method adjustCols (line 104) | func (f *File) adjustCols(ws *xlsxWorksheet, col, offset int) error {
  method adjustColDimensions (line 144) | func (f *File) adjustColDimensions(sheet string, ws *xlsxWorksheet, col,...
  method adjustRowDimensions (line 180) | func (f *File) adjustRowDimensions(sheet string, ws *xlsxWorksheet, row,...
  method adjustSingleRowDimensions (line 222) | func (r *xlsxRow) adjustSingleRowDimensions(offset int) {
  method adjustSingleRowFormulas (line 231) | func (f *File) adjustSingleRowFormulas(sheet, sheetN string, r *xlsxRow,...
  method adjustCellRef (line 241) | func (f *File) adjustCellRef(cellRef string, dir adjustDirection, num, o...
  method adjustFormula (line 283) | func (f *File) adjustFormula(sheet, sheetN string, cell *xlsxC, dir adju...
  function escapeSheetName (line 311) | func escapeSheetName(name string) string {
  function adjustFormulaColumnName (line 321) | func adjustFormulaColumnName(name, operand string, abs, keepRelative boo...
  function adjustFormulaRowNumber (line 340) | func adjustFormulaRowNumber(name, operand string, abs, keepRelative bool...
  function adjustFormulaOperandRef (line 358) | func adjustFormulaOperandRef(row, col, operand string, abs, keepRelative...
  method adjustFormulaOperand (line 369) | func (f *File) adjustFormulaOperand(sheet, sheetN string, keepRelative b...
  method adjustFormulaRef (line 419) | func (f *File) adjustFormulaRef(sheet, sheetN, formula string, keepRelat...
  function transformParenthesesToken (line 466) | func transformParenthesesToken(token efp.Token) string {
  function adjustRangeSheetName (line 478) | func adjustRangeSheetName(rng, source, target string) string {
  type arrayFormulaOperandToken (line 500) | type arrayFormulaOperandToken struct
    method setCoordinates (line 507) | func (af *arrayFormulaOperandToken) setCoordinates() error {
  function transformArrayFormula (line 545) | func transformArrayFormula(tokens []efp.Token, afs []arrayFormulaOperand...
  function getArrayFormulaTokens (line 574) | func getArrayFormulaTokens(sheet, formula string, definedNames []Defined...
  method adjustHyperlinks (line 605) | func (f *File) adjustHyperlinks(ws *xlsxWorksheet, sheet string, dir adj...
  method adjustTable (line 639) | func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDi...
  method adjustAutoFilter (line 690) | func (f *File) adjustAutoFilter(ws *xlsxWorksheet, sheet string, dir adj...
  method adjustAutoFilterHelper (line 722) | func (f *File) adjustAutoFilterHelper(dir adjustDirection, coordinates [...
  method adjustMergeCells (line 743) | func (f *File) adjustMergeCells(ws *xlsxWorksheet, sheet string, dir adj...
  method adjustMergeCellsHelper (line 792) | func (f *File) adjustMergeCellsHelper(p1, p2, num, offset int) (int, int) {
  method deleteMergeCell (line 816) | func (f *File) deleteMergeCell(ws *xlsxWorksheet, idx int) {
  function adjustCellName (line 828) | func adjustCellName(cell string, dir adjustDirection, c, r, offset int) ...
  method adjustCalcChain (line 839) | func (f *File) adjustCalcChain(ws *xlsxWorksheet, sheet string, dir adju...
  method adjustVolatileDepsTopic (line 881) | func (vt *xlsxVolTypes) adjustVolatileDepsTopic(cell string, dir adjustD...
  method adjustVolatileDeps (line 910) | func (f *File) adjustVolatileDeps(ws *xlsxWorksheet, sheet string, dir a...
  method adjustConditionalFormats (line 935) | func (f *File) adjustConditionalFormats(ws *xlsxWorksheet, sheet string,...
  method adjustDataValidations (line 958) | func (f *File) adjustDataValidations(ws *xlsxWorksheet, sheet string, di...
  method adjustDrawings (line 1012) | func (from *xlsxFrom) adjustDrawings(dir adjustDirection, num, offset in...
  method adjustDrawings (line 1033) | func (to *xlsxTo) adjustDrawings(dir adjustDirection, num, offset int, o...
  method adjustDrawings (line 1051) | func (a *xdrCellAnchor) adjustDrawings(dir adjustDirection, num, offset ...
  method adjustDrawings (line 1068) | func (a *xlsxCellAnchorPos) adjustDrawings(dir adjustDirection, num, off...
  method adjustDrawings (line 1084) | func (f *File) adjustDrawings(ws *xlsxWorksheet, sheet string, dir adjus...
  method adjustDefinedNames (line 1143) | func (f *File) adjustDefinedNames(sheet string, dir adjustDirection, num...

FILE: adjust_test.go
  function TestAdjustMergeCells (line 15) | func TestAdjustMergeCells(t *testing.T) {
  function TestAdjustAutoFilter (line 289) | func TestAdjustAutoFilter(t *testing.T) {
  function TestAdjustTable (line 312) | func TestAdjustTable(t *testing.T) {
  function TestAdjustHelper (line 344) | func TestAdjustHelper(t *testing.T) {
  function TestAdjustCalcChain (line 361) | func TestAdjustCalcChain(t *testing.T) {
  function TestAdjustCols (line 382) | func TestAdjustCols(t *testing.T) {
  function TestAdjustColDimensions (line 477) | func TestAdjustColDimensions(t *testing.T) {
  function TestAdjustRowDimensions (line 491) | func TestAdjustRowDimensions(t *testing.T) {
  function TestAdjustHyperlinks (line 513) | func TestAdjustHyperlinks(t *testing.T) {
  function TestAdjustFormula (line 554) | func TestAdjustFormula(t *testing.T) {
  function TestAdjustVolatileDeps (line 974) | func TestAdjustVolatileDeps(t *testing.T) {
  function TestAdjustConditionalFormats (line 994) | func TestAdjustConditionalFormats(t *testing.T) {
  function TestAdjustDataValidations (line 1076) | func TestAdjustDataValidations(t *testing.T) {
  function TestAdjustDrawings (line 1194) | func TestAdjustDrawings(t *testing.T) {
  function TestAdjustDefinedNames (line 1277) | func TestAdjustDefinedNames(t *testing.T) {

FILE: calc.go
  constant formulaErrorDIV (line 42) | formulaErrorDIV         = "#DIV/0!"
  constant formulaErrorNAME (line 43) | formulaErrorNAME        = "#NAME?"
  constant formulaErrorNA (line 44) | formulaErrorNA          = "#N/A"
  constant formulaErrorNUM (line 45) | formulaErrorNUM         = "#NUM!"
  constant formulaErrorVALUE (line 46) | formulaErrorVALUE       = "#VALUE!"
  constant formulaErrorREF (line 47) | formulaErrorREF         = "#REF!"
  constant formulaErrorNULL (line 48) | formulaErrorNULL        = "#NULL!"
  constant formulaErrorSPILL (line 49) | formulaErrorSPILL       = "#SPILL!"
  constant formulaErrorCALC (line 50) | formulaErrorCALC        = "#CALC!"
  constant formulaErrorGETTINGDATA (line 51) | formulaErrorGETTINGDATA = "#GETTING_DATA"
  constant _ (line 53) | _ byte = iota
  constant criteriaEq (line 54) | criteriaEq
  constant criteriaLe (line 55) | criteriaLe
  constant criteriaGe (line 56) | criteriaGe
  constant criteriaNe (line 57) | criteriaNe
  constant criteriaL (line 58) | criteriaL
  constant criteriaG (line 59) | criteriaG
  constant criteriaErr (line 60) | criteriaErr
  constant criteriaRegexp (line 61) | criteriaRegexp
  constant categoryWeightAndMass (line 63) | categoryWeightAndMass
  constant categoryDistance (line 64) | categoryDistance
  constant categoryTime (line 65) | categoryTime
  constant categoryPressure (line 66) | categoryPressure
  constant categoryForce (line 67) | categoryForce
  constant categoryEnergy (line 68) | categoryEnergy
  constant categoryPower (line 69) | categoryPower
  constant categoryMagnetism (line 70) | categoryMagnetism
  constant categoryTemperature (line 71) | categoryTemperature
  constant categoryVolumeAndLiquidMeasure (line 72) | categoryVolumeAndLiquidMeasure
  constant categoryArea (line 73) | categoryArea
  constant categoryInformation (line 74) | categoryInformation
  constant categorySpeed (line 75) | categorySpeed
  constant matchModeExact (line 77) | matchModeExact      = 0
  constant matchModeMinGreater (line 78) | matchModeMinGreater = 1
  constant matchModeMaxLess (line 79) | matchModeMaxLess    = -1
  constant matchModeWildcard (line 80) | matchModeWildcard   = 2
  constant searchModeLinear (line 82) | searchModeLinear        = 1
  constant searchModeReverseLinear (line 83) | searchModeReverseLinear = -1
  constant searchModeAscBinary (line 84) | searchModeAscBinary     = 2
  constant searchModeDescBinary (line 85) | searchModeDescBinary    = -2
  constant maxFinancialIterations (line 87) | maxFinancialIterations = 128
  constant financialPrecision (line 88) | financialPrecision     = 1.0e-08
  constant monthRe (line 90) | monthRe    = `((jan|january)|(feb|february)|(mar|march)|(apr|april)|(may...
  constant df1 (line 91) | df1        = `(([0-9])+)/(([0-9])+)/(([0-9])+)`
  constant df2 (line 92) | df2        = monthRe + ` (([0-9])+), (([0-9])+)`
  constant df3 (line 93) | df3        = `(([0-9])+)-(([0-9])+)-(([0-9])+)`
  constant df4 (line 94) | df4        = `(([0-9])+)-` + monthRe + `-(([0-9])+)`
  constant datePrefix (line 95) | datePrefix = `^((` + df1 + `|` + df2 + `|` + df3 + `|` + df4 + `) )?`
  constant tfhh (line 96) | tfhh       = `(([0-9])+) (am|pm)`
  constant tfhhmm (line 97) | tfhhmm     = `(([0-9])+):(([0-9])+)( (am|pm))?`
  constant tfmmss (line 98) | tfmmss     = `(([0-9])+):(([0-9])+\.([0-9])+)( (am|pm))?`
  constant tfhhmmss (line 99) | tfhhmmss   = `(([0-9])+):(([0-9])+):(([0-9])+(\.([0-9])+)?)( (am|pm))?`
  constant timeSuffix (line 100) | timeSuffix = `( (` + tfhh + `|` + tfhhmm + `|` + tfmmss + `|` + tfhhmmss...
  type calcContext (line 255) | type calcContext struct
  type cellRef (line 264) | type cellRef struct
  type cellRange (line 271) | type cellRange struct
    method prepareCellRange (line 1598) | func (cr *cellRange) prepareCellRange(col, row bool, cellRef cellRef) ...
  type formulaCriteria (line 277) | type formulaCriteria struct
  type ArgType (line 283) | type ArgType
  constant ArgUnknown (line 287) | ArgUnknown ArgType = iota
  constant ArgNumber (line 288) | ArgNumber
  constant ArgString (line 289) | ArgString
  constant ArgList (line 290) | ArgList
  constant ArgMatrix (line 291) | ArgMatrix
  constant ArgError (line 292) | ArgError
  constant ArgEmpty (line 293) | ArgEmpty
  type formulaArg (line 297) | type formulaArg struct
    method Value (line 310) | func (fa formulaArg) Value() (value string) {
    method ToNumber (line 333) | func (fa formulaArg) ToNumber() formulaArg {
    method ToBool (line 353) | func (fa formulaArg) ToBool() formulaArg {
    method ToList (line 371) | func (fa formulaArg) ToList() []formulaArg {
  type formulaFuncs (line 388) | type formulaFuncs struct
    method implicitIntersect (line 399) | func (fn *formulaFuncs) implicitIntersect(arg formulaArg) formulaArg {
    method BESSELI (line 1965) | func (fn *formulaFuncs) BESSELI(argsList *list.List) formulaArg {
    method BESSELJ (line 1976) | func (fn *formulaFuncs) BESSELJ(argsList *list.List) formulaArg {
    method bassel (line 1984) | func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) form...
    method BESSELK (line 2023) | func (fn *formulaFuncs) BESSELK(argsList *list.List) formulaArg {
    method besselK0 (line 2050) | func (fn *formulaFuncs) besselK0(x formulaArg) float64 {
    method besselK1 (line 2069) | func (fn *formulaFuncs) besselK1(x formulaArg) float64 {
    method besselK2 (line 2087) | func (fn *formulaFuncs) besselK2(x, n formulaArg) float64 {
    method BESSELY (line 2102) | func (fn *formulaFuncs) BESSELY(argsList *list.List) formulaArg {
    method besselY0 (line 2129) | func (fn *formulaFuncs) besselY0(x formulaArg) float64 {
    method besselY1 (line 2152) | func (fn *formulaFuncs) besselY1(x formulaArg) float64 {
    method besselY2 (line 2168) | func (fn *formulaFuncs) besselY2(x, n formulaArg) float64 {
    method BIN2DEC (line 2182) | func (fn *formulaFuncs) BIN2DEC(argsList *list.List) formulaArg {
    method BIN2HEX (line 2198) | func (fn *formulaFuncs) BIN2HEX(argsList *list.List) formulaArg {
    method BIN2OCT (line 2225) | func (fn *formulaFuncs) BIN2OCT(argsList *list.List) formulaArg {
    method bin2dec (line 2249) | func (fn *formulaFuncs) bin2dec(number string) formulaArg {
    method BITAND (line 2272) | func (fn *formulaFuncs) BITAND(argsList *list.List) formulaArg {
    method BITLSHIFT (line 2280) | func (fn *formulaFuncs) BITLSHIFT(argsList *list.List) formulaArg {
    method BITOR (line 2288) | func (fn *formulaFuncs) BITOR(argsList *list.List) formulaArg {
    method BITRSHIFT (line 2296) | func (fn *formulaFuncs) BITRSHIFT(argsList *list.List) formulaArg {
    method BITXOR (line 2304) | func (fn *formulaFuncs) BITXOR(argsList *list.List) formulaArg {
    method bitwise (line 2310) | func (fn *formulaFuncs) bitwise(name string, argsList *list.List) form...
    method COMPLEX (line 2338) | func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg {
    method CONVERT (line 2891) | func (fn *formulaFuncs) CONVERT(argsList *list.List) formulaArg {
    method DEC2BIN (line 2922) | func (fn *formulaFuncs) DEC2BIN(argsList *list.List) formulaArg {
    method DEC2HEX (line 2930) | func (fn *formulaFuncs) DEC2HEX(argsList *list.List) formulaArg {
    method DEC2OCT (line 2938) | func (fn *formulaFuncs) DEC2OCT(argsList *list.List) formulaArg {
    method dec2x (line 2944) | func (fn *formulaFuncs) dec2x(name string, argsList *list.List) formul...
    method DELTA (line 3017) | func (fn *formulaFuncs) DELTA(argsList *list.List) formulaArg {
    method ERF (line 3041) | func (fn *formulaFuncs) ERF(argsList *list.List) formulaArg {
    method ERFdotPRECISE (line 3066) | func (fn *formulaFuncs) ERFdotPRECISE(argsList *list.List) formulaArg {
    method erfc (line 3078) | func (fn *formulaFuncs) erfc(name string, argsList *list.List) formula...
    method ERFC (line 3094) | func (fn *formulaFuncs) ERFC(argsList *list.List) formulaArg {
    method ERFCdotPRECISE (line 3103) | func (fn *formulaFuncs) ERFCdotPRECISE(argsList *list.List) formulaArg {
    method GESTEP (line 3111) | func (fn *formulaFuncs) GESTEP(argsList *list.List) formulaArg {
    method HEX2BIN (line 3135) | func (fn *formulaFuncs) HEX2BIN(argsList *list.List) formulaArg {
    method HEX2DEC (line 3157) | func (fn *formulaFuncs) HEX2DEC(argsList *list.List) formulaArg {
    method HEX2OCT (line 3168) | func (fn *formulaFuncs) HEX2OCT(argsList *list.List) formulaArg {
    method hex2dec (line 3187) | func (fn *formulaFuncs) hex2dec(number string) formulaArg {
    method IMABS (line 3207) | func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg {
    method IMAGINARY (line 3223) | func (fn *formulaFuncs) IMAGINARY(argsList *list.List) formulaArg {
    method IMARGUMENT (line 3239) | func (fn *formulaFuncs) IMARGUMENT(argsList *list.List) formulaArg {
    method IMCONJUGATE (line 3255) | func (fn *formulaFuncs) IMCONJUGATE(argsList *list.List) formulaArg {
    method IMCOS (line 3271) | func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg {
    method IMCOSH (line 3287) | func (fn *formulaFuncs) IMCOSH(argsList *list.List) formulaArg {
    method IMCOT (line 3303) | func (fn *formulaFuncs) IMCOT(argsList *list.List) formulaArg {
    method IMCSC (line 3319) | func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg {
    method IMCSCH (line 3339) | func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg {
    method IMDIV (line 3359) | func (fn *formulaFuncs) IMDIV(argsList *list.List) formulaArg {
    method IMEXP (line 3383) | func (fn *formulaFuncs) IMEXP(argsList *list.List) formulaArg {
    method IMLN (line 3399) | func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg {
    method IMLOG10 (line 3419) | func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg {
    method IMLOG2 (line 3439) | func (fn *formulaFuncs) IMLOG2(argsList *list.List) formulaArg {
    method IMPOWER (line 3459) | func (fn *formulaFuncs) IMPOWER(argsList *list.List) formulaArg {
    method IMPRODUCT (line 3486) | func (fn *formulaFuncs) IMPRODUCT(argsList *list.List) formulaArg {
    method IMREAL (line 3524) | func (fn *formulaFuncs) IMREAL(argsList *list.List) formulaArg {
    method IMSEC (line 3540) | func (fn *formulaFuncs) IMSEC(argsList *list.List) formulaArg {
    method IMSECH (line 3556) | func (fn *formulaFuncs) IMSECH(argsList *list.List) formulaArg {
    method IMSIN (line 3572) | func (fn *formulaFuncs) IMSIN(argsList *list.List) formulaArg {
    method IMSINH (line 3588) | func (fn *formulaFuncs) IMSINH(argsList *list.List) formulaArg {
    method IMSQRT (line 3604) | func (fn *formulaFuncs) IMSQRT(argsList *list.List) formulaArg {
    method IMSUB (line 3621) | func (fn *formulaFuncs) IMSUB(argsList *list.List) formulaArg {
    method IMSUM (line 3640) | func (fn *formulaFuncs) IMSUM(argsList *list.List) formulaArg {
    method IMTAN (line 3660) | func (fn *formulaFuncs) IMTAN(argsList *list.List) formulaArg {
    method OCT2BIN (line 3676) | func (fn *formulaFuncs) OCT2BIN(argsList *list.List) formulaArg {
    method OCT2DEC (line 3700) | func (fn *formulaFuncs) OCT2DEC(argsList *list.List) formulaArg {
    method OCT2HEX (line 3716) | func (fn *formulaFuncs) OCT2HEX(argsList *list.List) formulaArg {
    method oct2dec (line 3737) | func (fn *formulaFuncs) oct2dec(number string) formulaArg {
    method ABS (line 3756) | func (fn *formulaFuncs) ABS(argsList *list.List) formulaArg {
    method ACOS (line 3772) | func (fn *formulaFuncs) ACOS(argsList *list.List) formulaArg {
    method ACOSH (line 3787) | func (fn *formulaFuncs) ACOSH(argsList *list.List) formulaArg {
    method ACOT (line 3803) | func (fn *formulaFuncs) ACOT(argsList *list.List) formulaArg {
    method ACOTH (line 3818) | func (fn *formulaFuncs) ACOTH(argsList *list.List) formulaArg {
    method AGGREGATE (line 3833) | func (fn *formulaFuncs) AGGREGATE(argsList *list.List) formulaArg {
    method ARABIC (line 3883) | func (fn *formulaFuncs) ARABIC(argsList *list.List) formulaArg {
    method ASIN (line 3936) | func (fn *formulaFuncs) ASIN(argsList *list.List) formulaArg {
    method ASINH (line 3951) | func (fn *formulaFuncs) ASINH(argsList *list.List) formulaArg {
    method ATAN (line 3967) | func (fn *formulaFuncs) ATAN(argsList *list.List) formulaArg {
    method ATANH (line 3982) | func (fn *formulaFuncs) ATANH(argsList *list.List) formulaArg {
    method ATAN2 (line 3998) | func (fn *formulaFuncs) ATAN2(argsList *list.List) formulaArg {
    method BASE (line 4017) | func (fn *formulaFuncs) BASE(argsList *list.List) formulaArg {
    method CEILING (line 4053) | func (fn *formulaFuncs) CEILING(argsList *list.List) formulaArg {
    method CEILINGdotMATH (line 4093) | func (fn *formulaFuncs) CEILINGdotMATH(argsList *list.List) formulaArg {
    method CEILINGdotPRECISE (line 4142) | func (fn *formulaFuncs) CEILINGdotPRECISE(argsList *list.List) formula...
    method COMBIN (line 4185) | func (fn *formulaFuncs) COMBIN(argsList *list.List) formulaArg {
    method COMBINA (line 4217) | func (fn *formulaFuncs) COMBINA(argsList *list.List) formulaArg {
    method COS (line 4255) | func (fn *formulaFuncs) COS(argsList *list.List) formulaArg {
    method COSH (line 4270) | func (fn *formulaFuncs) COSH(argsList *list.List) formulaArg {
    method COT (line 4285) | func (fn *formulaFuncs) COT(argsList *list.List) formulaArg {
    method COTH (line 4303) | func (fn *formulaFuncs) COTH(argsList *list.List) formulaArg {
    method CSC (line 4321) | func (fn *formulaFuncs) CSC(argsList *list.List) formulaArg {
    method CSCH (line 4339) | func (fn *formulaFuncs) CSCH(argsList *list.List) formulaArg {
    method DECIMAL (line 4357) | func (fn *formulaFuncs) DECIMAL(argsList *list.List) formulaArg {
    method DEGREES (line 4381) | func (fn *formulaFuncs) DEGREES(argsList *list.List) formulaArg {
    method EVEN (line 4400) | func (fn *formulaFuncs) EVEN(argsList *list.List) formulaArg {
    method EXP (line 4425) | func (fn *formulaFuncs) EXP(argsList *list.List) formulaArg {
    method FACT (line 4449) | func (fn *formulaFuncs) FACT(argsList *list.List) formulaArg {
    method FACTDOUBLE (line 4467) | func (fn *formulaFuncs) FACTDOUBLE(argsList *list.List) formulaArg {
    method FLOOR (line 4489) | func (fn *formulaFuncs) FLOOR(argsList *list.List) formulaArg {
    method FLOORdotMATH (line 4518) | func (fn *formulaFuncs) FLOORdotMATH(argsList *list.List) formulaArg {
    method FLOORdotPRECISE (line 4561) | func (fn *formulaFuncs) FLOORdotPRECISE(argsList *list.List) formulaArg {
    method GCD (line 4622) | func (fn *formulaFuncs) GCD(argsList *list.List) formulaArg {
    method INT (line 4664) | func (fn *formulaFuncs) INT(argsList *list.List) formulaArg {
    method ISOdotCEILING (line 4684) | func (fn *formulaFuncs) ISOdotCEILING(argsList *list.List) formulaArg {
    method LCM (line 4736) | func (fn *formulaFuncs) LCM(argsList *list.List) formulaArg {
    method LN (line 4780) | func (fn *formulaFuncs) LN(argsList *list.List) formulaArg {
    method LOG (line 4795) | func (fn *formulaFuncs) LOG(argsList *list.List) formulaArg {
    method LOG10 (line 4830) | func (fn *formulaFuncs) LOG10(argsList *list.List) formulaArg {
    method MDETERM (line 4914) | func (fn *formulaFuncs) MDETERM(argsList *list.List) (result formulaAr...
    method MINVERSE (line 4975) | func (fn *formulaFuncs) MINVERSE(argsList *list.List) formulaArg {
    method MMULT (line 4999) | func (fn *formulaFuncs) MMULT(argsList *list.List) formulaArg {
    method MOD (line 5046) | func (fn *formulaFuncs) MOD(argsList *list.List) formulaArg {
    method MROUND (line 5072) | func (fn *formulaFuncs) MROUND(argsList *list.List) formulaArg {
    method MULTINOMIAL (line 5103) | func (fn *formulaFuncs) MULTINOMIAL(argsList *list.List) formulaArg {
    method MUNIT (line 5129) | func (fn *formulaFuncs) MUNIT(argsList *list.List) (result formulaArg) {
    method ODD (line 5157) | func (fn *formulaFuncs) ODD(argsList *list.List) formulaArg {
    method PI (line 5185) | func (fn *formulaFuncs) PI(argsList *list.List) formulaArg {
    method POWER (line 5196) | func (fn *formulaFuncs) POWER(argsList *list.List) formulaArg {
    method PRODUCT (line 5221) | func (fn *formulaFuncs) PRODUCT(argsList *list.List) formulaArg {
    method QUOTIENT (line 5251) | func (fn *formulaFuncs) QUOTIENT(argsList *list.List) formulaArg {
    method RADIANS (line 5272) | func (fn *formulaFuncs) RADIANS(argsList *list.List) formulaArg {
    method RAND (line 5287) | func (fn *formulaFuncs) RAND(argsList *list.List) formulaArg {
    method RANDBETWEEN (line 5298) | func (fn *formulaFuncs) RANDBETWEEN(argsList *list.List) formulaArg {
    method ROMAN (line 5436) | func (fn *formulaFuncs) ROMAN(argsList *list.List) formulaArg {
    method round (line 5491) | func (fn *formulaFuncs) round(number, digits float64, mode roundMode) ...
    method ROUND (line 5522) | func (fn *formulaFuncs) ROUND(argsList *list.List) formulaArg {
    method ROUNDDOWN (line 5541) | func (fn *formulaFuncs) ROUNDDOWN(argsList *list.List) formulaArg {
    method ROUNDUP (line 5560) | func (fn *formulaFuncs) ROUNDUP(argsList *list.List) formulaArg {
    method SEC (line 5579) | func (fn *formulaFuncs) SEC(argsList *list.List) formulaArg {
    method SECH (line 5594) | func (fn *formulaFuncs) SECH(argsList *list.List) formulaArg {
    method SERIESSUM (line 5609) | func (fn *formulaFuncs) SERIESSUM(argsList *list.List) formulaArg {
    method SIGN (line 5644) | func (fn *formulaFuncs) SIGN(argsList *list.List) formulaArg {
    method SIN (line 5665) | func (fn *formulaFuncs) SIN(argsList *list.List) formulaArg {
    method SINH (line 5680) | func (fn *formulaFuncs) SINH(argsList *list.List) formulaArg {
    method SQRT (line 5695) | func (fn *formulaFuncs) SQRT(argsList *list.List) formulaArg {
    method SQRTPI (line 5713) | func (fn *formulaFuncs) SQRTPI(argsList *list.List) formulaArg {
    method STDEV (line 5728) | func (fn *formulaFuncs) STDEV(argsList *list.List) formulaArg {
    method STDEVdotS (line 5739) | func (fn *formulaFuncs) STDEVdotS(argsList *list.List) formulaArg {
    method STDEVA (line 5751) | func (fn *formulaFuncs) STDEVA(argsList *list.List) formulaArg {
    method stdev (line 5793) | func (fn *formulaFuncs) stdev(stdeva bool, argsList *list.List) formul...
    method POISSONdotDIST (line 5834) | func (fn *formulaFuncs) POISSONdotDIST(argsList *list.List) formulaArg {
    method POISSON (line 5846) | func (fn *formulaFuncs) POISSON(argsList *list.List) formulaArg {
    method PROB (line 5913) | func (fn *formulaFuncs) PROB(argsList *list.List) formulaArg {
    method SUBTOTAL (line 5948) | func (fn *formulaFuncs) SUBTOTAL(argsList *list.List) formulaArg {
    method SUM (line 5983) | func (fn *formulaFuncs) SUM(argsList *list.List) formulaArg {
    method SUMIF (line 6014) | func (fn *formulaFuncs) SUMIF(argsList *list.List) formulaArg {
    method SUMIFS (line 6052) | func (fn *formulaFuncs) SUMIFS(argsList *list.List) formulaArg {
    method sumproduct (line 6076) | func (fn *formulaFuncs) sumproduct(argsList *list.List) formulaArg {
    method SUMPRODUCT (line 6129) | func (fn *formulaFuncs) SUMPRODUCT(argsList *list.List) formulaArg {
    method SUMSQ (line 6145) | func (fn *formulaFuncs) SUMSQ(argsList *list.List) formulaArg {
    method sumx (line 6180) | func (fn *formulaFuncs) sumx(name string, argsList *list.List) formula...
    method SUMX2MY2 (line 6211) | func (fn *formulaFuncs) SUMX2MY2(argsList *list.List) formulaArg {
    method SUMX2PY2 (line 6219) | func (fn *formulaFuncs) SUMX2PY2(argsList *list.List) formulaArg {
    method SUMXMY2 (line 6228) | func (fn *formulaFuncs) SUMXMY2(argsList *list.List) formulaArg {
    method TAN (line 6236) | func (fn *formulaFuncs) TAN(argsList *list.List) formulaArg {
    method TANH (line 6251) | func (fn *formulaFuncs) TANH(argsList *list.List) formulaArg {
    method TRUNC (line 6266) | func (fn *formulaFuncs) TRUNC(argsList *list.List) formulaArg {
    method AVEDEV (line 6303) | func (fn *formulaFuncs) AVEDEV(argsList *list.List) formulaArg {
    method AVERAGE (line 6327) | func (fn *formulaFuncs) AVERAGE(argsList *list.List) formulaArg {
    method AVERAGEA (line 6343) | func (fn *formulaFuncs) AVERAGEA(argsList *list.List) formulaArg {
    method AVERAGEIF (line 6361) | func (fn *formulaFuncs) AVERAGEIF(argsList *list.List) formulaArg {
    method AVERAGEIFS (line 6413) | func (fn *formulaFuncs) AVERAGEIFS(argsList *list.List) formulaArg {
    method prepareBETAdotDISTArgs (line 6640) | func (fn *formulaFuncs) prepareBETAdotDISTArgs(argsList *list.List) fo...
    method BETAdotDIST (line 6685) | func (fn *formulaFuncs) BETAdotDIST(argsList *list.List) formulaArg {
    method BETADIST (line 6709) | func (fn *formulaFuncs) BETADIST(argsList *list.List) formulaArg {
    method betainv (line 7059) | func (fn *formulaFuncs) betainv(name string, argsList *list.List) form...
    method BETAINV (line 7106) | func (fn *formulaFuncs) BETAINV(argsList *list.List) formulaArg {
    method BETAdotINV (line 7115) | func (fn *formulaFuncs) BETAdotINV(argsList *list.List) formulaArg {
    method BINOMdotDIST (line 7148) | func (fn *formulaFuncs) BINOMdotDIST(argsList *list.List) formulaArg {
    method BINOMDIST (line 7160) | func (fn *formulaFuncs) BINOMDIST(argsList *list.List) formulaArg {
    method BINOMdotDISTdotRANGE (line 7199) | func (fn *formulaFuncs) BINOMdotDISTdotRANGE(argsList *list.List) form...
    method BINOMdotINV (line 7266) | func (fn *formulaFuncs) BINOMdotINV(argsList *list.List) formulaArg {
    method CHIDIST (line 7298) | func (fn *formulaFuncs) CHIDIST(argsList *list.List) formulaArg {
    method CHIINV (line 7361) | func (fn *formulaFuncs) CHIINV(argsList *list.List) formulaArg {
    method CHITEST (line 7388) | func (fn *formulaFuncs) CHITEST(argsList *list.List) formulaArg {
    method CHISQdotDIST (line 7583) | func (fn *formulaFuncs) CHISQdotDIST(argsList *list.List) formulaArg {
    method CHISQdotDISTdotRT (line 7614) | func (fn *formulaFuncs) CHISQdotDISTdotRT(argsList *list.List) formula...
    method CHISQdotTEST (line 7627) | func (fn *formulaFuncs) CHISQdotTEST(argsList *list.List) formulaArg {
    method CHISQdotINV (line 7725) | func (fn *formulaFuncs) CHISQdotINV(argsList *list.List) formulaArg {
    method CHISQdotINVdotRT (line 7753) | func (fn *formulaFuncs) CHISQdotINVdotRT(argsList *list.List) formulaA...
    method confidence (line 7762) | func (fn *formulaFuncs) confidence(name string, argsList *list.List) f...
    method CONFIDENCE (line 7802) | func (fn *formulaFuncs) CONFIDENCE(argsList *list.List) formulaArg {
    method CONFIDENCEdotNORM (line 7813) | func (fn *formulaFuncs) CONFIDENCEdotNORM(argsList *list.List) formula...
    method CONFIDENCEdotT (line 7824) | func (fn *formulaFuncs) CONFIDENCEdotT(argsList *list.List) formulaArg {
    method covar (line 7854) | func (fn *formulaFuncs) covar(name string, argsList *list.List) formul...
    method COVAR (line 7889) | func (fn *formulaFuncs) COVAR(argsList *list.List) formulaArg {
    method COVARIANCEdotP (line 7897) | func (fn *formulaFuncs) COVARIANCEdotP(argsList *list.List) formulaArg {
    method COVARIANCEdotS (line 7905) | func (fn *formulaFuncs) COVARIANCEdotS(argsList *list.List) formulaArg {
    method countSum (line 7922) | func (fn *formulaFuncs) countSum(countText bool, args []formulaArg) (c...
    method CORREL (line 7956) | func (fn *formulaFuncs) CORREL(argsList *list.List) formulaArg {
    method COUNT (line 7995) | func (fn *formulaFuncs) COUNT(argsList *list.List) formulaArg {
    method COUNTA (line 8023) | func (fn *formulaFuncs) COUNTA(argsList *list.List) formulaArg {
    method COUNTBLANK (line 8054) | func (fn *formulaFuncs) COUNTBLANK(argsList *list.List) formulaArg {
    method COUNTIF (line 8071) | func (fn *formulaFuncs) COUNTIF(argsList *list.List) formulaArg {
    method COUNTIFS (line 8121) | func (fn *formulaFuncs) COUNTIFS(argsList *list.List) formulaArg {
    method CRITBINOM (line 8142) | func (fn *formulaFuncs) CRITBINOM(argsList *list.List) formulaArg {
    method DEVSQ (line 8153) | func (fn *formulaFuncs) DEVSQ(argsList *list.List) formulaArg {
    method FISHER (line 8181) | func (fn *formulaFuncs) FISHER(argsList *list.List) formulaArg {
    method FISHERINV (line 8208) | func (fn *formulaFuncs) FISHERINV(argsList *list.List) formulaArg {
    method FORECAST (line 8229) | func (fn *formulaFuncs) FORECAST(argsList *list.List) formulaArg {
    method FORECASTdotLINEAR (line 8237) | func (fn *formulaFuncs) FORECASTdotLINEAR(argsList *list.List) formula...
    method FREQUENCY (line 8270) | func (fn *formulaFuncs) FREQUENCY(argsList *list.List) formulaArg {
    method GAMMA (line 8318) | func (fn *formulaFuncs) GAMMA(argsList *list.List) formulaArg {
    method GAMMAdotDIST (line 8337) | func (fn *formulaFuncs) GAMMAdotDIST(argsList *list.List) formulaArg {
    method GAMMADIST (line 8349) | func (fn *formulaFuncs) GAMMADIST(argsList *list.List) formulaArg {
    method GAMMAdotINV (line 8411) | func (fn *formulaFuncs) GAMMAdotINV(argsList *list.List) formulaArg {
    method GAMMAINV (line 8422) | func (fn *formulaFuncs) GAMMAINV(argsList *list.List) formulaArg {
    method GAMMALN (line 8449) | func (fn *formulaFuncs) GAMMALN(argsList *list.List) formulaArg {
    method GAMMALNdotPRECISE (line 8467) | func (fn *formulaFuncs) GAMMALNdotPRECISE(argsList *list.List) formula...
    method GAUSS (line 8486) | func (fn *formulaFuncs) GAUSS(argsList *list.List) formulaArg {
    method GEOMEAN (line 8506) | func (fn *formulaFuncs) GEOMEAN(argsList *list.List) formulaArg {
    method trendGrowth (line 9153) | func (fn *formulaFuncs) trendGrowth(name string, argsList *list.List) ...
    method GROWTH (line 9209) | func (fn *formulaFuncs) GROWTH(argsList *list.List) formulaArg {
    method HARMEAN (line 9217) | func (fn *formulaFuncs) HARMEAN(argsList *list.List) formulaArg {
    method prepareHYPGEOMDISTArgs (line 9261) | func (fn *formulaFuncs) prepareHYPGEOMDISTArgs(name string, argsList *...
    method HYPGEOMdotDIST (line 9298) | func (fn *formulaFuncs) HYPGEOMdotDIST(argsList *list.List) formulaArg {
    method HYPGEOMDIST (line 9323) | func (fn *formulaFuncs) HYPGEOMDIST(argsList *list.List) formulaArg {
    method INTERCEPT (line 9339) | func (fn *formulaFuncs) INTERCEPT(argsList *list.List) formulaArg {
    method KURT (line 9347) | func (fn *formulaFuncs) KURT(argsList *list.List) formulaArg {
    method EXPONdotDIST (line 9390) | func (fn *formulaFuncs) EXPONdotDIST(argsList *list.List) formulaArg {
    method EXPONDIST (line 9403) | func (fn *formulaFuncs) EXPONDIST(argsList *list.List) formulaArg {
    method FdotDIST (line 9435) | func (fn *formulaFuncs) FdotDIST(argsList *list.List) formulaArg {
    method FDIST (line 9473) | func (fn *formulaFuncs) FDIST(argsList *list.List) formulaArg {
    method FdotDISTdotRT (line 9511) | func (fn *formulaFuncs) FdotDISTdotRT(argsList *list.List) formulaArg {
    method prepareFinvArgs (line 9520) | func (fn *formulaFuncs) prepareFinvArgs(name string, argsList *list.Li...
    method FdotINV (line 9550) | func (fn *formulaFuncs) FdotINV(argsList *list.List) formulaArg {
    method FdotINVdotRT (line 9564) | func (fn *formulaFuncs) FdotINVdotRT(argsList *list.List) formulaArg {
    method FINV (line 9577) | func (fn *formulaFuncs) FINV(argsList *list.List) formulaArg {
    method FdotTEST (line 9592) | func (fn *formulaFuncs) FdotTEST(argsList *list.List) formulaArg {
    method FTEST (line 9648) | func (fn *formulaFuncs) FTEST(argsList *list.List) formulaArg {
    method LOGINV (line 9660) | func (fn *formulaFuncs) LOGINV(argsList *list.List) formulaArg {
    method LOGNORMdotINV (line 9693) | func (fn *formulaFuncs) LOGNORMdotINV(argsList *list.List) formulaArg {
    method LOGNORMdotDIST (line 9705) | func (fn *formulaFuncs) LOGNORMdotDIST(argsList *list.List) formulaArg {
    method LOGNORMDIST (line 9741) | func (fn *formulaFuncs) LOGNORMDIST(argsList *list.List) formulaArg {
    method MODE (line 9769) | func (fn *formulaFuncs) MODE(argsList *list.List) formulaArg {
    method MODEdotMULT (line 9812) | func (fn *formulaFuncs) MODEdotMULT(argsList *list.List) formulaArg {
    method MODEdotSNGL (line 9859) | func (fn *formulaFuncs) MODEdotSNGL(argsList *list.List) formulaArg {
    method NEGBINOMdotDIST (line 9873) | func (fn *formulaFuncs) NEGBINOMdotDIST(argsList *list.List) formulaArg {
    method NEGBINOMDIST (line 9905) | func (fn *formulaFuncs) NEGBINOMDIST(argsList *list.List) formulaArg {
    method NORMdotDIST (line 9930) | func (fn *formulaFuncs) NORMdotDIST(argsList *list.List) formulaArg {
    method NORMDIST (line 9942) | func (fn *formulaFuncs) NORMDIST(argsList *list.List) formulaArg {
    method NORMdotINV (line 9973) | func (fn *formulaFuncs) NORMdotINV(argsList *list.List) formulaArg {
    method NORMINV (line 9985) | func (fn *formulaFuncs) NORMINV(argsList *list.List) formulaArg {
    method NORMdotSdotDIST (line 10017) | func (fn *formulaFuncs) NORMdotSdotDIST(argsList *list.List) formulaArg {
    method NORMSDIST (line 10033) | func (fn *formulaFuncs) NORMSDIST(argsList *list.List) formulaArg {
    method NORMSINV (line 10050) | func (fn *formulaFuncs) NORMSINV(argsList *list.List) formulaArg {
    method NORMdotSdotINV (line 10066) | func (fn *formulaFuncs) NORMdotSdotINV(argsList *list.List) formulaArg {
    method kth (line 10123) | func (fn *formulaFuncs) kth(name string, argsList *list.List) formulaA...
    method LARGE (line 10156) | func (fn *formulaFuncs) LARGE(argsList *list.List) formulaArg {
    method MAX (line 10164) | func (fn *formulaFuncs) MAX(argsList *list.List) formulaArg {
    method MAXA (line 10177) | func (fn *formulaFuncs) MAXA(argsList *list.List) formulaArg {
    method MAXIFS (line 10189) | func (fn *formulaFuncs) MAXIFS(argsList *list.List) formulaArg {
    method maxValue (line 10225) | func (fn *formulaFuncs) maxValue(maxa bool, argsList *list.List) formu...
    method MEDIAN (line 10264) | func (fn *formulaFuncs) MEDIAN(argsList *list.List) formulaArg {
    method MIN (line 10307) | func (fn *formulaFuncs) MIN(argsList *list.List) formulaArg {
    method MINA (line 10320) | func (fn *formulaFuncs) MINA(argsList *list.List) formulaArg {
    method MINIFS (line 10332) | func (fn *formulaFuncs) MINIFS(argsList *list.List) formulaArg {
    method minValue (line 10368) | func (fn *formulaFuncs) minValue(mina bool, argsList *list.List) formu...
    method pearsonProduct (line 10405) | func (fn *formulaFuncs) pearsonProduct(name string, n int, argsList *l...
    method PEARSON (line 10462) | func (fn *formulaFuncs) PEARSON(argsList *list.List) formulaArg {
    method PERCENTILEdotEXC (line 10471) | func (fn *formulaFuncs) PERCENTILEdotEXC(argsList *list.List) formulaA...
    method PERCENTILEdotINC (line 10506) | func (fn *formulaFuncs) PERCENTILEdotINC(argsList *list.List) formulaA...
    method PERCENTILE (line 10518) | func (fn *formulaFuncs) PERCENTILE(argsList *list.List) formulaArg {
    method percentrank (line 10553) | func (fn *formulaFuncs) percentrank(name string, argsList *list.List) ...
    method PERCENTRANKdotEXC (line 10608) | func (fn *formulaFuncs) PERCENTRANKdotEXC(argsList *list.List) formula...
    method PERCENTRANKdotINC (line 10617) | func (fn *formulaFuncs) PERCENTRANKdotINC(argsList *list.List) formula...
    method PERCENTRANK (line 10625) | func (fn *formulaFuncs) PERCENTRANK(argsList *list.List) formulaArg {
    method PERMUT (line 10633) | func (fn *formulaFuncs) PERMUT(argsList *list.List) formulaArg {
    method PERMUTATIONA (line 10656) | func (fn *formulaFuncs) PERMUTATIONA(argsList *list.List) formulaArg {
    method PHI (line 10679) | func (fn *formulaFuncs) PHI(argsList *list.List) formulaArg {
    method QUARTILE (line 10694) | func (fn *formulaFuncs) QUARTILE(argsList *list.List) formulaArg {
    method QUARTILEdotEXC (line 10716) | func (fn *formulaFuncs) QUARTILEdotEXC(argsList *list.List) formulaArg {
    method QUARTILEdotINC (line 10737) | func (fn *formulaFuncs) QUARTILEdotINC(argsList *list.List) formulaArg {
    method rank (line 10745) | func (fn *formulaFuncs) rank(name string, argsList *list.List) formula...
    method RANKdotEQ (line 10783) | func (fn *formulaFuncs) RANKdotEQ(argsList *list.List) formulaArg {
    method RANK (line 10792) | func (fn *formulaFuncs) RANK(argsList *list.List) formulaArg {
    method RSQ (line 10801) | func (fn *formulaFuncs) RSQ(argsList *list.List) formulaArg {
    method skew (line 10806) | func (fn *formulaFuncs) skew(name string, argsList *list.List) formula...
    method SKEW (line 10851) | func (fn *formulaFuncs) SKEW(argsList *list.List) formulaArg {
    method SKEWdotP (line 10859) | func (fn *formulaFuncs) SKEWdotP(argsList *list.List) formulaArg {
    method SLOPE (line 10869) | func (fn *formulaFuncs) SLOPE(argsList *list.List) formulaArg {
    method SMALL (line 10877) | func (fn *formulaFuncs) SMALL(argsList *list.List) formulaArg {
    method STANDARDIZE (line 10886) | func (fn *formulaFuncs) STANDARDIZE(argsList *list.List) formulaArg {
    method stdevp (line 10910) | func (fn *formulaFuncs) stdevp(name string, argsList *list.List) formu...
    method STDEVP (line 10929) | func (fn *formulaFuncs) STDEVP(argsList *list.List) formulaArg {
    method STDEVdotP (line 10937) | func (fn *formulaFuncs) STDEVdotP(argsList *list.List) formulaArg {
    method STDEVPA (line 10945) | func (fn *formulaFuncs) STDEVPA(argsList *list.List) formulaArg {
    method STEYX (line 10953) | func (fn *formulaFuncs) STEYX(argsList *list.List) formulaArg {
    method TdotDIST (line 11013) | func (fn *formulaFuncs) TdotDIST(argsList *list.List) formulaArg {
    method TdotDISTdot2T (line 11048) | func (fn *formulaFuncs) TdotDISTdot2T(argsList *list.List) formulaArg {
    method TdotDISTdotRT (line 11071) | func (fn *formulaFuncs) TdotDISTdotRT(argsList *list.List) formulaArg {
    method TDIST (line 11097) | func (fn *formulaFuncs) TDIST(argsList *list.List) formulaArg {
    method TdotINV (line 11123) | func (fn *formulaFuncs) TdotINV(argsList *list.List) formulaArg {
    method TdotINVdot2T (line 11159) | func (fn *formulaFuncs) TdotINVdot2T(argsList *list.List) formulaArg {
    method TINV (line 11187) | func (fn *formulaFuncs) TINV(argsList *list.List) formulaArg {
    method TREND (line 11200) | func (fn *formulaFuncs) TREND(argsList *list.List) formulaArg {
    method tTest (line 11244) | func (fn *formulaFuncs) tTest(mtx1, mtx2 [][]formulaArg, fTails, fTyp ...
    method TTEST (line 11292) | func (fn *formulaFuncs) TTEST(argsList *list.List) formulaArg {
    method TdotTEST (line 11323) | func (fn *formulaFuncs) TdotTEST(argsList *list.List) formulaArg {
    method TRIMMEAN (line 11334) | func (fn *formulaFuncs) TRIMMEAN(argsList *list.List) formulaArg {
    method vars (line 11373) | func (fn *formulaFuncs) vars(name string, argsList *list.List) formula...
    method VAR (line 11418) | func (fn *formulaFuncs) VAR(argsList *list.List) formulaArg {
    method VARA (line 11426) | func (fn *formulaFuncs) VARA(argsList *list.List) formulaArg {
    method VARP (line 11434) | func (fn *formulaFuncs) VARP(argsList *list.List) formulaArg {
    method VARdotP (line 11442) | func (fn *formulaFuncs) VARdotP(argsList *list.List) formulaArg {
    method VARdotS (line 11450) | func (fn *formulaFuncs) VARdotS(argsList *list.List) formulaArg {
    method VARPA (line 11458) | func (fn *formulaFuncs) VARPA(argsList *list.List) formulaArg {
    method WEIBULL (line 11467) | func (fn *formulaFuncs) WEIBULL(argsList *list.List) formulaArg {
    method WEIBULLdotDIST (line 11493) | func (fn *formulaFuncs) WEIBULLdotDIST(argsList *list.List) formulaArg {
    method ZdotTEST (line 11504) | func (fn *formulaFuncs) ZdotTEST(argsList *list.List) formulaArg {
    method ZTEST (line 11519) | func (fn *formulaFuncs) ZTEST(argsList *list.List) formulaArg {
    method ERRORdotTYPE (line 11559) | func (fn *formulaFuncs) ERRORdotTYPE(argsList *list.List) formulaArg {
    method ISBLANK (line 11582) | func (fn *formulaFuncs) ISBLANK(argsList *list.List) formulaArg {
    method ISERR (line 11601) | func (fn *formulaFuncs) ISERR(argsList *list.List) formulaArg {
    method ISERROR (line 11626) | func (fn *formulaFuncs) ISERROR(argsList *list.List) formulaArg {
    method ISEVEN (line 11651) | func (fn *formulaFuncs) ISEVEN(argsList *list.List) formulaArg {
    method ISFORMULA (line 11678) | func (fn *formulaFuncs) ISFORMULA(argsList *list.List) formulaArg {
    method ISLOGICAL (line 11698) | func (fn *formulaFuncs) ISLOGICAL(argsList *list.List) formulaArg {
    method ISNA (line 11714) | func (fn *formulaFuncs) ISNA(argsList *list.List) formulaArg {
    method ISNONTEXT (line 11729) | func (fn *formulaFuncs) ISNONTEXT(argsList *list.List) formulaArg {
    method ISNUMBER (line 11744) | func (fn *formulaFuncs) ISNUMBER(argsList *list.List) formulaArg {
    method ISODD (line 11761) | func (fn *formulaFuncs) ISODD(argsList *list.List) formulaArg {
    method ISREF (line 11780) | func (fn *formulaFuncs) ISREF(argsList *list.List) formulaArg {
    method ISTEXT (line 11795) | func (fn *formulaFuncs) ISTEXT(argsList *list.List) formulaArg {
    method N (line 11810) | func (fn *formulaFuncs) N(argsList *list.List) formulaArg {
    method NA (line 11832) | func (fn *formulaFuncs) NA(argsList *list.List) formulaArg {
    method SHEET (line 11843) | func (fn *formulaFuncs) SHEET(argsList *list.List) formulaArg {
    method SHEETS (line 11873) | func (fn *formulaFuncs) SHEETS(argsList *list.List) formulaArg {
    method TYPE (line 11902) | func (fn *formulaFuncs) TYPE(argsList *list.List) formulaArg {
    method T (line 11927) | func (fn *formulaFuncs) T(argsList *list.List) formulaArg {
    method AND (line 11947) | func (fn *formulaFuncs) AND(argsList *list.List) formulaArg {
    method FALSE (line 11982) | func (fn *formulaFuncs) FALSE(argsList *list.List) formulaArg {
    method IFERROR (line 11993) | func (fn *formulaFuncs) IFERROR(argsList *list.List) formulaArg {
    method IFNA (line 12013) | func (fn *formulaFuncs) IFNA(argsList *list.List) formulaArg {
    method IFS (line 12030) | func (fn *formulaFuncs) IFS(argsList *list.List) formulaArg {
    method NOT (line 12047) | func (fn *formulaFuncs) NOT(argsList *list.List) formulaArg {
    method OR (line 12072) | func (fn *formulaFuncs) OR(argsList *list.List) formulaArg {
    method SWITCH (line 12116) | func (fn *formulaFuncs) SWITCH(argsList *list.List) formulaArg {
    method TRUE (line 12146) | func (fn *formulaFuncs) TRUE(argsList *list.List) formulaArg {
    method XOR (line 12190) | func (fn *formulaFuncs) XOR(argsList *list.List) formulaArg {
    method DATE (line 12203) | func (fn *formulaFuncs) DATE(argsList *list.List) formulaArg {
    method DATEDIF (line 12254) | func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
    method DATEVALUE (line 12534) | func (fn *formulaFuncs) DATEVALUE(argsList *list.List) formulaArg {
    method DAY (line 12556) | func (fn *formulaFuncs) DAY(argsList *list.List) formulaArg {
    method DAYS (line 12588) | func (fn *formulaFuncs) DAYS(argsList *list.List) formulaArg {
    method DAYS360 (line 12604) | func (fn *formulaFuncs) DAYS360(argsList *list.List) formulaArg {
    method ISOWEEKNUM (line 12654) | func (fn *formulaFuncs) ISOWEEKNUM(argsList *list.List) formulaArg {
    method EDATE (line 12686) | func (fn *formulaFuncs) EDATE(argsList *list.List) formulaArg {
    method EOMONTH (line 12740) | func (fn *formulaFuncs) EOMONTH(argsList *list.List) formulaArg {
    method HOUR (line 12787) | func (fn *formulaFuncs) HOUR(argsList *list.List) formulaArg {
    method MINUTE (line 12820) | func (fn *formulaFuncs) MINUTE(argsList *list.List) formulaArg {
    method MONTH (line 12851) | func (fn *formulaFuncs) MONTH(argsList *list.List) formulaArg {
    method NETWORKDAYS (line 13010) | func (fn *formulaFuncs) NETWORKDAYS(argsList *list.List) formulaArg {
    method NETWORKDAYSdotINTL (line 13033) | func (fn *formulaFuncs) NETWORKDAYSdotINTL(argsList *list.List) formul...
    method WORKDAY (line 13089) | func (fn *formulaFuncs) WORKDAY(argsList *list.List) formulaArg {
    method WORKDAYdotINTL (line 13112) | func (fn *formulaFuncs) WORKDAYdotINTL(argsList *list.List) formulaArg {
    method YEAR (line 13173) | func (fn *formulaFuncs) YEAR(argsList *list.List) formulaArg {
    method YEARFRAC (line 13320) | func (fn *formulaFuncs) YEARFRAC(argsList *list.List) formulaArg {
    method NOW (line 13342) | func (fn *formulaFuncs) NOW(argsList *list.List) formulaArg {
    method SECOND (line 13355) | func (fn *formulaFuncs) SECOND(argsList *list.List) formulaArg {
    method TIME (line 13387) | func (fn *formulaFuncs) TIME(argsList *list.List) formulaArg {
    method TIMEVALUE (line 13408) | func (fn *formulaFuncs) TIMEVALUE(argsList *list.List) formulaArg {
    method TODAY (line 13438) | func (fn *formulaFuncs) TODAY(argsList *list.List) formulaArg {
    method WEEKDAY (line 13467) | func (fn *formulaFuncs) WEEKDAY(argsList *list.List) formulaArg {
    method weeknum (line 13519) | func (fn *formulaFuncs) weeknum(snTime time.Time, returnType int) form...
    method WEEKNUM (line 13559) | func (fn *formulaFuncs) WEEKNUM(argsList *list.List) formulaArg {
    method ARRAYTOTEXT (line 13625) | func (fn *formulaFuncs) ARRAYTOTEXT(argsList *list.List) formulaArg {
    method BAHTTEXT (line 13722) | func (fn *formulaFuncs) BAHTTEXT(argsList *list.List) formulaArg {
    method CHAR (line 13778) | func (fn *formulaFuncs) CHAR(argsList *list.List) formulaArg {
    method CLEAN (line 13797) | func (fn *formulaFuncs) CLEAN(argsList *list.List) formulaArg {
    method CODE (line 13815) | func (fn *formulaFuncs) CODE(argsList *list.List) formulaArg {
    method code (line 13820) | func (fn *formulaFuncs) code(name string, argsList *list.List) formula...
    method CONCAT (line 13838) | func (fn *formulaFuncs) CONCAT(argsList *list.List) formulaArg {
    method CONCATENATE (line 13846) | func (fn *formulaFuncs) CONCATENATE(argsList *list.List) formulaArg {
    method concat (line 13852) | func (fn *formulaFuncs) concat(argsList *list.List) formulaArg {
    method DBCS (line 13869) | func (fn *formulaFuncs) DBCS(argsList *list.List) formulaArg {
    method EXACT (line 13904) | func (fn *formulaFuncs) EXACT(argsList *list.List) formulaArg {
    method FIXED (line 13917) | func (fn *formulaFuncs) FIXED(argsList *list.List) formulaArg {
    method FIND (line 13966) | func (fn *formulaFuncs) FIND(argsList *list.List) formulaArg {
    method FINDB (line 13976) | func (fn *formulaFuncs) FINDB(argsList *list.List) formulaArg {
    method prepareFindArgs (line 13982) | func (fn *formulaFuncs) prepareFindArgs(name string, argsList *list.Li...
    method find (line 14005) | func (fn *formulaFuncs) find(name string, argsList *list.List) formula...
    method LEFT (line 14058) | func (fn *formulaFuncs) LEFT(argsList *list.List) formulaArg {
    method LEFTB (line 14066) | func (fn *formulaFuncs) LEFTB(argsList *list.List) formulaArg {
    method leftRight (line 14072) | func (fn *formulaFuncs) leftRight(name string, argsList *list.List) fo...
    method LEN (line 14115) | func (fn *formulaFuncs) LEN(argsList *list.List) formulaArg {
    method LENB (line 14128) | func (fn *formulaFuncs) LENB(argsList *list.List) formulaArg {
    method LOWER (line 14148) | func (fn *formulaFuncs) LOWER(argsList *list.List) formulaArg {
    method MID (line 14159) | func (fn *formulaFuncs) MID(argsList *list.List) formulaArg {
    method MIDB (line 14168) | func (fn *formulaFuncs) MIDB(argsList *list.List) formulaArg {
    method mid (line 14173) | func (fn *formulaFuncs) mid(name string, argsList *list.List) formulaA...
    method PROPER (line 14237) | func (fn *formulaFuncs) PROPER(argsList *list.List) formulaArg {
    method REPLACE (line 14258) | func (fn *formulaFuncs) REPLACE(argsList *list.List) formulaArg {
    method REPLACEB (line 14266) | func (fn *formulaFuncs) REPLACEB(argsList *list.List) formulaArg {
    method replace (line 14273) | func (fn *formulaFuncs) replace(name string, argsList *list.List) form...
    method REPT (line 14304) | func (fn *formulaFuncs) REPT(argsList *list.List) formulaArg {
    method RIGHT (line 14333) | func (fn *formulaFuncs) RIGHT(argsList *list.List) formulaArg {
    method RIGHTB (line 14341) | func (fn *formulaFuncs) RIGHTB(argsList *list.List) formulaArg {
    method SEARCH (line 14349) | func (fn *formulaFuncs) SEARCH(argsList *list.List) formulaArg {
    method SEARCHB (line 14358) | func (fn *formulaFuncs) SEARCHB(argsList *list.List) formulaArg {
    method SUBSTITUTE (line 14366) | func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg {
    method TEXT (line 14411) | func (fn *formulaFuncs) TEXT(argsList *list.List) formulaArg {
    method prepareTextAfterBefore (line 14431) | func (fn *formulaFuncs) prepareTextAfterBefore(name string, argsList *...
    method textAfterBefore (line 14524) | func (fn *formulaFuncs) textAfterBefore(name string, argsList *list.Li...
    method TEXTAFTER (line 14574) | func (fn *formulaFuncs) TEXTAFTER(argsList *list.List) formulaArg {
    method TEXTBEFORE (line 14582) | func (fn *formulaFuncs) TEXTBEFORE(argsList *list.List) formulaArg {
    method TEXTJOIN (line 14591) | func (fn *formulaFuncs) TEXTJOIN(argsList *list.List) formulaArg {
    method TRIM (line 14648) | func (fn *formulaFuncs) TRIM(argsList *list.List) formulaArg {
    method UNICHAR (line 14659) | func (fn *formulaFuncs) UNICHAR(argsList *list.List) formulaArg {
    method UNICODE (line 14677) | func (fn *formulaFuncs) UNICODE(argsList *list.List) formulaArg {
    method UNIQUE (line 14685) | func (fn *formulaFuncs) UNIQUE(argsList *list.List) formulaArg {
    method UPPER (line 14818) | func (fn *formulaFuncs) UPPER(argsList *list.List) formulaArg {
    method VALUE (line 14829) | func (fn *formulaFuncs) VALUE(argsList *list.List) formulaArg {
    method VALUETOTEXT (line 14866) | func (fn *formulaFuncs) VALUETOTEXT(argsList *list.List) formulaArg {
    method IF (line 14885) | func (fn *formulaFuncs) IF(argsList *list.List) formulaArg {
    method ADDRESS (line 14938) | func (fn *formulaFuncs) ADDRESS(argsList *list.List) formulaArg {
    method ANCHORARRAY (line 14989) | func (fn *formulaFuncs) ANCHORARRAY(argsList *list.List) formulaArg {
    method CHOOSE (line 15031) | func (fn *formulaFuncs) CHOOSE(argsList *list.List) formulaArg {
    method COLUMN (line 15189) | func (fn *formulaFuncs) COLUMN(argsList *list.List) formulaArg {
    method COLUMNS (line 15244) | func (fn *formulaFuncs) COLUMNS(argsList *list.List) formulaArg {
    method FORMULATEXT (line 15266) | func (fn *formulaFuncs) FORMULATEXT(argsList *list.List) formulaArg {
    method HLOOKUP (line 15332) | func (fn *formulaFuncs) HLOOKUP(argsList *list.List) formulaArg {
    method HYPERLINK (line 15361) | func (fn *formulaFuncs) HYPERLINK(argsList *list.List) formulaArg {
    method MATCH (line 15470) | func (fn *formulaFuncs) MATCH(argsList *list.List) formulaArg {
    method TRANSPOSE (line 15506) | func (fn *formulaFuncs) TRANSPOSE(argsList *list.List) formulaArg {
    method VLOOKUP (line 15582) | func (fn *formulaFuncs) VLOOKUP(argsList *list.List) formulaArg {
    method index (line 15714) | func (fn *formulaFuncs) index(array formulaArg, rowIdx, colIdx int) fo...
    method prepareXlookupArgs (line 15753) | func (fn *formulaFuncs) prepareXlookupArgs(argsList *list.List) formul...
    method xlookup (line 15788) | func (fn *formulaFuncs) xlookup(lookupRows, lookupCols, returnArrayRow...
    method XLOOKUP (line 15840) | func (fn *formulaFuncs) XLOOKUP(argsList *list.List) formulaArg {
    method INDEX (line 15876) | func (fn *formulaFuncs) INDEX(argsList *list.List) formulaArg {
    method INDIRECT (line 15916) | func (fn *formulaFuncs) INDIRECT(argsList *list.List) formulaArg {
    method LOOKUP (line 15978) | func (fn *formulaFuncs) LOOKUP(argsList *list.List) formulaArg {
    method ROW (line 16021) | func (fn *formulaFuncs) ROW(argsList *list.List) formulaArg {
    method ROWS (line 16042) | func (fn *formulaFuncs) ROWS(argsList *list.List) formulaArg {
    method ENCODEURL (line 16067) | func (fn *formulaFuncs) ENCODEURL(argsList *list.List) formulaArg {
    method ACCRINT (line 16086) | func (fn *formulaFuncs) ACCRINT(argsList *list.List) formulaArg {
    method ACCRINTM (line 16129) | func (fn *formulaFuncs) ACCRINTM(argsList *list.List) formulaArg {
    method prepareAmorArgs (line 16164) | func (fn *formulaFuncs) prepareAmorArgs(name string, argsList *list.Li...
    method AMORDEGRC (line 16216) | func (fn *formulaFuncs) AMORDEGRC(argsList *list.List) formulaArg {
    method AMORLINC (line 16266) | func (fn *formulaFuncs) AMORLINC(argsList *list.List) formulaArg {
    method prepareCouponArgs (line 16296) | func (fn *formulaFuncs) prepareCouponArgs(name string, argsList *list....
    method COUPDAYBS (line 16395) | func (fn *formulaFuncs) COUPDAYBS(argsList *list.List) formulaArg {
    method COUPDAYS (line 16409) | func (fn *formulaFuncs) COUPDAYS(argsList *list.List) formulaArg {
    method COUPDAYSNC (line 16428) | func (fn *formulaFuncs) COUPDAYSNC(argsList *list.List) formulaArg {
    method coupons (line 16440) | func (fn *formulaFuncs) coupons(name string, arg formulaArg) formulaArg {
    method COUPNCD (line 16478) | func (fn *formulaFuncs) COUPNCD(argsList *list.List) formulaArg {
    method COUPNUM (line 16491) | func (fn *formulaFuncs) COUPNUM(argsList *list.List) formulaArg {
    method COUPPCD (line 16504) | func (fn *formulaFuncs) COUPPCD(argsList *list.List) formulaArg {
    method CUMIPMT (line 16516) | func (fn *formulaFuncs) CUMIPMT(argsList *list.List) formulaArg {
    method CUMPRINC (line 16525) | func (fn *formulaFuncs) CUMPRINC(argsList *list.List) formulaArg {
    method cumip (line 16530) | func (fn *formulaFuncs) cumip(name string, argsList *list.List) formul...
    method DB (line 16592) | func (fn *formulaFuncs) DB(argsList *list.List) formulaArg {
    method DDB (line 16648) | func (fn *formulaFuncs) DDB(argsList *list.List) formulaArg {
    method prepareDataValueArgs (line 16693) | func (fn *formulaFuncs) prepareDataValueArgs(n int, argsList *list.Lis...
    method discIntrate (line 16729) | func (fn *formulaFuncs) discIntrate(name string, argsList *list.List) ...
    method DISC (line 16778) | func (fn *formulaFuncs) DISC(argsList *list.List) formulaArg {
    method DOLLAR (line 16787) | func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg {
    method DOLLARDE (line 16832) | func (fn *formulaFuncs) DOLLARDE(argsList *list.List) formulaArg {
    method DOLLARFR (line 16841) | func (fn *formulaFuncs) DOLLARFR(argsList *list.List) formulaArg {
    method dollar (line 16846) | func (fn *formulaFuncs) dollar(name string, argsList *list.List) formu...
    method prepareDurationArgs (line 16877) | func (fn *formulaFuncs) prepareDurationArgs(name string, argsList *lis...
    method duration (line 16920) | func (fn *formulaFuncs) duration(settlement, maturity, coupon, yld, fr...
    method DURATION (line 16956) | func (fn *formulaFuncs) DURATION(argsList *list.List) formulaArg {
    method EFFECT (line 16969) | func (fn *formulaFuncs) EFFECT(argsList *list.List) formulaArg {
    method EUROCONVERT (line 16993) | func (fn *formulaFuncs) EUROCONVERT(argsList *list.List) formulaArg {
    method FV (line 17073) | func (fn *formulaFuncs) FV(argsList *list.List) formulaArg {
    method FVSCHEDULE (line 17116) | func (fn *formulaFuncs) FVSCHEDULE(argsList *list.List) formulaArg {
    method INTRATE (line 17142) | func (fn *formulaFuncs) INTRATE(argsList *list.List) formulaArg {
    method IPMT (line 17151) | func (fn *formulaFuncs) IPMT(argsList *list.List) formulaArg {
    method ipmt (line 17174) | func (fn *formulaFuncs) ipmt(name string, argsList *list.List) formula...
    method IRR (line 17229) | func (fn *formulaFuncs) IRR(argsList *list.List) formulaArg {
    method ISPMT (line 17297) | func (fn *formulaFuncs) ISPMT(argsList *list.List) formulaArg {
    method MDURATION (line 17333) | func (fn *formulaFuncs) MDURATION(argsList *list.List) formulaArg {
    method MIRR (line 17351) | func (fn *formulaFuncs) MIRR(argsList *list.List) formulaArg {
    method NOMINAL (line 17384) | func (fn *formulaFuncs) NOMINAL(argsList *list.List) formulaArg {
    method NPER (line 17407) | func (fn *formulaFuncs) NPER(argsList *list.List) formulaArg {
    method NPV (line 17455) | func (fn *formulaFuncs) NPV(argsList *list.List) formulaArg {
    method prepareOddfArgs (line 17579) | func (fn *formulaFuncs) prepareOddfArgs(name string, argsList *list.Li...
    method ODDFPRICE (line 17632) | func (fn *formulaFuncs) ODDFPRICE(argsList *list.List) formulaArg {
    method ODDFYIELD (line 17776) | func (fn *formulaFuncs) ODDFYIELD(argsList *list.List) formulaArg {
    method prepareOddlArgs (line 17816) | func (fn *formulaFuncs) prepareOddlArgs(name string, argsList *list.Li...
    method oddl (line 17863) | func (fn *formulaFuncs) oddl(name string, argsList *list.List) formula...
    method ODDLPRICE (line 17936) | func (fn *formulaFuncs) ODDLPRICE(argsList *list.List) formulaArg {
    method ODDLYIELD (line 17944) | func (fn *formulaFuncs) ODDLYIELD(argsList *list.List) formulaArg {
    method PDURATION (line 17953) | func (fn *formulaFuncs) PDURATION(argsList *list.List) formulaArg {
    method PMT (line 17980) | func (fn *formulaFuncs) PMT(argsList *list.List) formulaArg {
    method PPMT (line 18025) | func (fn *formulaFuncs) PPMT(argsList *list.List) formulaArg {
    method price (line 18030) | func (fn *formulaFuncs) price(settlement, maturity, rate, yld, redempt...
    method priceYield (line 18103) | func (fn *formulaFuncs) priceYield(name string, argsList *list.List) f...
    method PRICE (line 18135) | func (fn *formulaFuncs) PRICE(argsList *list.List) formulaArg {
    method PRICEDISC (line 18143) | func (fn *formulaFuncs) PRICEDISC(argsList *list.List) formulaArg {
    method PRICEMAT (line 18186) | func (fn *formulaFuncs) PRICEMAT(argsList *list.List) formulaArg {
    method PV (line 18234) | func (fn *formulaFuncs) PV(argsList *list.List) formulaArg {
    method rate (line 18275) | func (fn *formulaFuncs) rate(nper, pmt, pv, fv, t, guess formulaArg) f...
    method RATE (line 18302) | func (fn *formulaFuncs) RATE(argsList *list.List) formulaArg {
    method RECEIVED (line 18349) | func (fn *formulaFuncs) RECEIVED(argsList *list.List) formulaArg {
    method RRI (line 18390) | func (fn *formulaFuncs) RRI(argsList *list.List) formulaArg {
    method SLN (line 18416) | func (fn *formulaFuncs) SLN(argsList *list.List) formulaArg {
    method SYD (line 18437) | func (fn *formulaFuncs) SYD(argsList *list.List) formulaArg {
    method TBILLEQ (line 18464) | func (fn *formulaFuncs) TBILLEQ(argsList *list.List) formulaArg {
    method TBILLPRICE (line 18491) | func (fn *formulaFuncs) TBILLPRICE(argsList *list.List) formulaArg {
    method TBILLYIELD (line 18518) | func (fn *formulaFuncs) TBILLYIELD(argsList *list.List) formulaArg {
    method prepareVdbArgs (line 18543) | func (fn *formulaFuncs) prepareVdbArgs(argsList *list.List) formulaArg {
    method vdb (line 18595) | func (fn *formulaFuncs) vdb(cost, salvage, life, life1, period, factor...
    method VDB (line 18633) | func (fn *formulaFuncs) VDB(argsList *list.List) formulaArg {
    method prepareXArgs (line 18673) | func (fn *formulaFuncs) prepareXArgs(values, dates formulaArg) (values...
    method xirr (line 18709) | func (fn *formulaFuncs) xirr(values, dates []float64, guess float64) f...
    method XIRR (line 18774) | func (fn *formulaFuncs) XIRR(argsList *list.List) formulaArg {
    method XNPV (line 18798) | func (fn *formulaFuncs) XNPV(argsList *list.List) formulaArg {
    method yield (line 18821) | func (fn *formulaFuncs) yield(settlement, maturity, rate, pr, redempti...
    method YIELD (line 18860) | func (fn *formulaFuncs) YIELD(argsList *list.List) formulaArg {
    method YIELDDISC (line 18868) | func (fn *formulaFuncs) YIELDDISC(argsList *list.List) formulaArg {
    method YIELDMAT (line 18908) | func (fn *formulaFuncs) YIELDMAT(argsList *list.List) formulaArg {
    method database (line 19062) | func (fn *formulaFuncs) database(name string, argsList *list.List) for...
    method DAVERAGE (line 19104) | func (fn *formulaFuncs) DAVERAGE(argsList *list.List) formulaArg {
    method dcount (line 19109) | func (fn *formulaFuncs) dcount(name string, argsList *list.List) formu...
    method DCOUNT (line 19142) | func (fn *formulaFuncs) DCOUNT(argsList *list.List) formulaArg {
    method DCOUNTA (line 19152) | func (fn *formulaFuncs) DCOUNTA(argsList *list.List) formulaArg {
    method DGET (line 19161) | func (fn *formulaFuncs) DGET(argsList *list.List) formulaArg {
    method DMAX (line 19187) | func (fn *formulaFuncs) DMAX(argsList *list.List) formulaArg {
    method DMIN (line 19197) | func (fn *formulaFuncs) DMIN(argsList *list.List) formulaArg {
    method DPRODUCT (line 19206) | func (fn *formulaFuncs) DPRODUCT(argsList *list.List) formulaArg {
    method DSTDEV (line 19216) | func (fn *formulaFuncs) DSTDEV(argsList *list.List) formulaArg {
    method DSTDEVP (line 19226) | func (fn *formulaFuncs) DSTDEVP(argsList *list.List) formulaArg {
    method DSUM (line 19235) | func (fn *formulaFuncs) DSUM(argsList *list.List) formulaArg {
    method DVAR (line 19245) | func (fn *formulaFuncs) DVAR(argsList *list.List) formulaArg {
    method DVARP (line 19255) | func (fn *formulaFuncs) DVARP(argsList *list.List) formulaArg {
    method DISPIMG (line 19263) | func (fn *formulaFuncs) DISPIMG(argsList *list.List) formulaArg {
    method SORTBY (line 19296) | func (fn *formulaFuncs) SORTBY(argsList *list.List) formulaArg {
  method CalcCellValue (line 878) | func (f *File) CalcCellValue(sheet, cell string, opts ...Options) (resul...
  method clearCalcCache (line 926) | func (f *File) clearCalcCache() {
  method calcCellValue (line 933) | func (f *File) calcCellValue(ctx *calcContext, sheet, cell string) (resu...
  function getPriority (line 948) | func getPriority(token efp.Token) (pri int) {
  function newNumberFormulaArg (line 960) | func newNumberFormulaArg(n float64) formulaArg {
  function newStringFormulaArg (line 968) | func newStringFormulaArg(s string) formulaArg {
  function newMatrixFormulaArg (line 973) | func newMatrixFormulaArg(m [][]formulaArg) formulaArg {
  function newListFormulaArg (line 978) | func newListFormulaArg(l []formulaArg) formulaArg {
  function newBoolFormulaArg (line 983) | func newBoolFormulaArg(b bool) formulaArg {
  function newErrorFormulaArg (line 993) | func newErrorFormulaArg(formulaError, msg string) formulaArg {
  function newEmptyFormulaArg (line 998) | func newEmptyFormulaArg() formulaArg {
  method evalInfixExp (line 1014) | func (f *File) evalInfixExp(ctx *calcContext, sheet, cell string, tokens...
  method evalInfixExpFunc (line 1146) | func (f *File) evalInfixExpFunc(ctx *calcContext, sheet, cell string, to...
  function prepareEvalInfixExp (line 1180) | func prepareEvalInfixExp(opfStack, opftStack, opfdStack, argsStack *Stac...
  function calcPow (line 1207) | func calcPow(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcEq (line 1221) | func calcEq(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcNEq (line 1231) | func calcNEq(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcL (line 1241) | func calcL(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcLe (line 1258) | func calcLe(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcG (line 1275) | func calcG(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcGe (line 1292) | func calcGe(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcSplice (line 1309) | func calcSplice(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcAdd (line 1315) | func calcAdd(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcSubtract (line 1329) | func calcSubtract(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcMultiply (line 1349) | func calcMultiply(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calcDiv (line 1363) | func calcDiv(rOpd, lOpd formulaArg, opdStack *Stack) error {
  function calculate (line 1380) | func calculate(opdStack *Stack, opt efp.Token) error {
  method parseOperatorPrefixToken (line 1437) | func (f *File) parseOperatorPrefixToken(optStack, opdStack *Stack, token...
  function isFunctionStartToken (line 1470) | func isFunctionStartToken(token efp.Token) bool {
  function isFunctionStopToken (line 1475) | func isFunctionStopToken(token efp.Token) bool {
  function isBeginParenthesesToken (line 1480) | func isBeginParenthesesToken(token efp.Token) bool {
  function isEndParenthesesToken (line 1485) | func isEndParenthesesToken(token efp.Token) bool {
  function isOperatorPrefixToken (line 1491) | func isOperatorPrefixToken(token efp.Token) bool {
  function isOperand (line 1497) | func isOperand(token efp.Token) bool {
  function tokenToFormulaArg (line 1502) | func tokenToFormulaArg(token efp.Token) formulaArg {
  function formulaArgToToken (line 1515) | func formulaArgToToken(arg formulaArg) efp.Token {
  method parseToken (line 1529) | func (f *File) parseToken(ctx *calcContext, sheet string, token efp.Toke...
  function parseRef (line 1572) | func parseRef(ref string) (cellRef, bool, bool, error) {
  method parseReference (line 1628) | func (f *File) parseReference(ctx *calcContext, sheet, reference string)...
  function prepareValueRange (line 1670) | func prepareValueRange(cr cellRange, valueRange []int) {
  function prepareValueRef (line 1686) | func prepareValueRef(cr cellRef, valueRange []int) {
  method cellResolver (line 1702) | func (f *File) cellResolver(ctx *calcContext, sheet, cell string) (formu...
  method rangeResolver (line 1764) | func (f *File) rangeResolver(ctx *calcContext, cellRefs, cellRanges *lis...
  function callFuncByName (line 1865) | func callFuncByName(receiver interface{}, name string, params []reflect....
  function formulaCriteriaParser (line 1879) | func formulaCriteriaParser(exp formulaArg) *formulaCriteria {
  function formulaCriteriaEval (line 1928) | func formulaCriteriaEval(val formulaArg, criteria *formulaCriteria) (res...
  function cmplx2str (line 2361) | func cmplx2str(num complex128, suffix string) string {
  function str2cmplx (line 2395) | func str2cmplx(c string) string {
  type conversionUnit (line 2405) | type conversionUnit struct
  function getUnitDetails (line 2801) | func getUnitDetails(uom string) (unit string, catgory byte, res float64,...
  function resolveTemperatureSynonyms (line 2843) | func resolveTemperatureSynonyms(uom string) string {
  function convertTemperature (line 2856) | func convertTemperature(fromUOM, toUOM string, value float64) float64 {
  function fact (line 4437) | func fact(number float64) float64 {
  function gcd (line 4600) | func gcd(x, y float64) float64 {
  function lcm (line 4723) | func lcm(a, b float64) float64 {
  function minor (line 4843) | func minor(sqMtx [][]float64, idx int) [][]float64 {
  function det (line 4862) | func det(sqMtx [][]float64) float64 {
  function newNumberMatrix (line 4879) | func newNumberMatrix(arg formulaArg, phalanx bool) (numMtx [][]float64, ...
  function newFormulaArgMatrix (line 4900) | func newFormulaArgMatrix(numMtx [][]float64) (arg [][]formulaArg) {
  function cofactorMatrix (line 4926) | func cofactorMatrix(i, j int, A [][]float64) float64 {
  function adjugateMatrix (line 4948) | func adjugateMatrix(A [][]float64) (adjA [][]float64) {
  type romanNumerals (line 5320) | type romanNumerals struct
  type roundMode (line 5482) | type roundMode
  constant closest (line 5485) | closest roundMode = iota
  constant down (line 5486) | down
  constant up (line 5487) | up
  function calcStdevPow (line 5759) | func calcStdevPow(result, count float64, n, m formulaArg) (float64, floa...
  function calcStdev (line 5770) | func calcStdev(stdeva bool, result, count float64, mean, token formulaAr...
  function prepareProbArgs (line 5876) | func prepareProbArgs(argsList *list.List) []formulaArg {
  function getBetaHelperContFrac (line 6439) | func getBetaHelperContFrac(fX, fA, fB float64) float64 {
  function getLanczosSum (line 6471) | func getLanczosSum(fZ float64) float64 {
  function getBeta (line 6523) | func getBeta(fAlpha, fBeta float64) float64 {
  function getBetaDistPDF (line 6552) | func getBetaDistPDF(fX, fA, fB float64) float64 {
  function getLogBeta (line 6574) | func getLogBeta(fAlpha, fBeta float64) float64 {
  function getBetaDist (line 6597) | func getBetaDist(fXin, fAlpha, fBeta float64) float64 {
  function d1mach (line 6752) | func d1mach(i int) float64 {
  function chebyshevInit (line 6770) | func chebyshevInit(nos int, eta float64, dos []float64) int {
  function chebyshevEval (line 6786) | func chebyshevEval(n int, x float64, a []float64) float64 {
  function lgammacor (line 6800) | func lgammacor(x float64) float64 {
  function logrelerr (line 6826) | func logrelerr(x float64) float64 {
  function logBeta (line 6863) | func logBeta(a, b float64) float64 {
  function pbetaRaw (line 6891) | func pbetaRaw(alnsml, ans, eps, p, pin, q, sml, x, y float64) float64 {
  function pbeta (line 6927) | func pbeta(x, pin, qin float64) (ans float64) {
  function betainvProbIterator (line 6973) | func betainvProbIterator(alpha1, alpha3, beta1, beta2, beta3, logBeta, m...
  function calcBetainv (line 7011) | func calcBetainv(probability, alpha, beta, lower, upper float64) float64 {
  function incompleteGamma (line 7120) | func incompleteGamma(a, x float64) float64 {
  function binomCoeff (line 7134) | func binomCoeff(n, k float64) float64 {
  function binomdist (line 7139) | func binomdist(x, n, p float64) float64 {
  function binominv (line 7241) | func binominv(n, p, alpha float64) float64 {
  function getGammaSeries (line 7430) | func getGammaSeries(fA, fX float64) float64 {
  function getGammaContFraction (line 7449) | func getGammaContFraction(fA, fX float64) float64 {
  function getLogGammaHelper (line 7495) | func getLogGammaHelper(fZ float64) float64 {
  function getGammaHelper (line 7502) | func getGammaHelper(fZ float64) float64 {
  function getLogGamma (line 7520) | func getLogGamma(fZ float64) float64 {
  function getLowRegIGamma (line 7535) | func getLowRegIGamma(fA, fX float64) float64 {
  function getChiSqDistCDF (line 7545) | func getChiSqDistCDF(fX, fDF float64) float64 {
  function getChiSqDistPDF (line 7554) | func getChiSqDistPDF(fX, fDF float64) float64 {
  function hasChangeOfSign (line 7635) | func hasChangeOfSign(u, w float64) bool {
  type calcInverseIterator (line 7641) | type calcInverseIterator struct
    method callBack (line 7647) | func (iterator *calcInverseIterator) callBack(x float64) float64 {
  function inverseQuadraticInterpolation (line 7656) | func inverseQuadraticInterpolation(iterator calcInverseIterator, fAx, fA...
  function calcIterateInverse (line 7693) | func calcIterateInverse(iterator calcInverseIterator, fAx, fBx float64) ...
  function calcStringCountSum (line 7910) | func calcStringCountSum(countText bool, count, sum float64, num, arg for...
  function formulaIfsMatch (line 8091) | func formulaIfsMatch(args []formulaArg) (cellRefs []cellRef) {
  function matrixToSortedColumnList (line 8243) | func matrixToSortedColumnList(arg formulaArg) formulaArg {
  function gammainv (line 8380) | func gammainv(probability, alpha, beta float64) float64 {
  function getNewMatrix (line 8523) | func getNewMatrix(c, r int) (matrix [][]float64) {
  function approxSub (line 8540) | func approxSub(a, b float64) float64 {
  function matrixClone (line 8548) | func matrixClone(matrix [][]float64) (cloneMatrix [][]float64) {
  type trendGrowthMatrixInfo (line 8564) | type trendGrowthMatrixInfo struct
  function prepareTrendGrowthMtxX (line 8570) | func prepareTrendGrowthMtxX(mtxX [][]float64) [][]float64 {
  function prepareTrendGrowthMtxY (line 8590) | func prepareTrendGrowthMtxY(bLOG bool, mtxY [][]float64) [][]float64 {
  function prepareTrendGrowth (line 8629) | func prepareTrendGrowth(bLOG bool, mtxX, mtxY [][]float64) (*trendGrowth...
  function calcPosition (line 8683) | func calcPosition(mtx [][]float64, idx int) (row, col int) {
  function getDouble (line 8694) | func getDouble(mtx [][]float64, idx int) float64 {
  function putDouble (line 8700) | func putDouble(mtx [][]float64, idx int, val float64) {
  function calcMeanOverAll (line 8706) | func calcMeanOverAll(mtx [][]float64, n int) float64 {
  function calcSumProduct (line 8718) | func calcSumProduct(mtxA, mtxB [][]float64, m int) float64 {
  function calcColumnMeans (line 8727) | func calcColumnMeans(mtxX, mtxRes [][]float64, c, r int) {
  function calcColumnsDelta (line 8738) | func calcColumnsDelta(mtx, columnMeans [][]float64, c, r int) {
  function calcSign (line 8748) | func calcSign(val float64) float64 {
  function calcColsMaximumNorm (line 8758) | func calcColsMaximumNorm(mtxA [][]float64, c, r, n int) float64 {
  function calcFastMult (line 8769) | func calcFastMult(mtxA, mtxB, mtxR [][]float64, n, m, l int) {
  function calcRowsEuclideanNorm (line 8785) | func calcRowsEuclideanNorm(mtxA [][]float64, c, r, n int) float64 {
  function calcRowsSumProduct (line 8796) | func calcRowsSumProduct(mtxA [][]float64, a int, mtxB [][]float64, b, r,...
  function calcSolveWithUpperRightTriangle (line 8805) | func calcSolveWithUpperRightTriangle(mtxA [][]float64, vecR []float64, m...
  function calcRowQRDecomposition (line 8823) | func calcRowQRDecomposition(mtxA [][]float64, vecR []float64, k, n int) ...
  function calcApplyColsHouseholderTransformation (line 8849) | func calcApplyColsHouseholderTransformation(mtxA [][]float64, r int, mtx...
  function calcRowMeans (line 8859) | func calcRowMeans(mtxX, mtxRes [][]float64, c, r int) {
  function calcRowsDelta (line 8870) | func calcRowsDelta(mtx, rowMeans [][]float64, c, r int) {
  function calcColumnMaximumNorm (line 8880) | func calcColumnMaximumNorm(mtxA [][]float64, r, c, n int) float64 {
  function calcColsEuclideanNorm (line 8892) | func calcColsEuclideanNorm(mtxA [][]float64, r, c, n int) float64 {
  function calcColsSumProduct (line 8901) | func calcColsSumProduct(mtxA [][]float64, a int, mtxB [][]float64, b, c,...
  function calcColQRDecomposition (line 8911) | func calcColQRDecomposition(mtxA [][]float64, vecR []float64, k, n int) ...
  function calcApplyRowsHouseholderTransformation (line 8943) | func calcApplyRowsHouseholderTransformation(mtxA [][]float64, c int, mtx...
  function calcTrendGrowthSimpleRegression (line 8953) | func calcTrendGrowthSimpleRegression(bConstant, bGrowth bool, mtxY, mtxX...
  function calcTrendGrowthMultipleRegressionPart1 (line 8996) | func calcTrendGrowthMultipleRegressionPart1(bConstant, bGrowth bool, mtx...
  function calcTrendGrowthMultipleRegressionPart2 (line 9042) | func calcTrendGrowthMultipleRegressionPart2(bConstant, bGrowth bool, mtx...
  function calcTrendGrowthRegression (line 9087) | func calcTrendGrowthRegression(bConstant, bGrowth bool, trendType, nCXN,...
  function calcTrendGrowth (line 9113) | func calcTrendGrowth(mtxY, mtxX, newX [][]float64, bConstant, bGrowth bo...
  function checkHYPGEOMDISTArgs (line 9248) | func checkHYPGEOMDISTArgs(sampleS, numberSample, populationS, numberPop ...
  function norminv (line 10079) | func norminv(p float64) (float64, error) {
  function calcListMatrixMax (line 10213) | func calcListMatrixMax(maxa bool, maxVal float64, arg formulaArg) float64 {
  function calcListMatrixMin (line 10356) | func calcListMatrixMin(mina bool, minVal float64, arg formulaArg) float64 {
  function getTDist (line 10987) | func getTDist(T, fDF, nType float64) float64 {
  function tTest (line 11205) | func tTest(bTemplin bool, mtx1, mtx2 [][]formulaArg, c1, c2, r1, r2 int)...
  function calcXor (line 12155) | func calcXor(argsList *list.List) formulaArg {
  function calcDateDif (line 12219) | func calcDateDif(unit string, diff float64, seq []int, startArg, endArg ...
  function isDateOnlyFmt (line 12299) | func isDateOnlyFmt(dateString string) bool {
  function isTimeOnlyFmt (line 12310) | func isTimeOnlyFmt(timeString string) bool {
  function strToTimePatternHandler1 (line 12322) | func strToTimePatternHandler1(subMatch []string) (h, m int, s float64, e...
  function strToTimePatternHandler2 (line 12329) | func strToTimePatternHandler2(subMatch []string) (h, m int, s float64, e...
  function strToTimePatternHandler3 (line 12339) | func strToTimePatternHandler3(subMatch []string) (h, m int, s float64, e...
  function strToTimePatternHandler4 (line 12349) | func strToTimePatternHandler4(subMatch []string) (h, m int, s float64, e...
  function strToTime (line 12361) | func strToTime(str string) (int, int, float64, bool, bool, formulaArg) {
  function strToDatePatternHandler1 (line 12412) | func strToDatePatternHandler1(subMatch []string) (int, int, int, bool, e...
  function strToDatePatternHandler2 (line 12432) | func strToDatePatternHandler2(subMatch []string) (int, int, int, bool, e...
  function strToDatePatternHandler3 (line 12450) | func strToDatePatternHandler3(subMatch []string) (int, int, int, bool, e...
  function strToDatePatternHandler4 (line 12480) | func strToDatePatternHandler4(subMatch []string) (int, int, int, bool, e...
  function strToDate (line 12494) | func strToDate(str string) (int, int, int, bool, formulaArg) {
  function genWeekendMask (line 12878) | func genWeekendMask(weekend int) []byte {
  function isWorkday (line 12893) | func isWorkday(weekendMask []byte, date float64) bool {
  function prepareWorkday (line 12904) | func prepareWorkday(weekend formulaArg) ([]byte, int) {
  function toExcelDateArg (line 12932) | func toExcelDateArg(arg formulaArg) formulaArg {
  function prepareHolidays (line 12956) | func prepareHolidays(args formulaArg) []int {
  function workdayIntl (line 12969) | func workdayIntl(endDate, sign int, holidays []int, weekendMask []byte, ...
  function yearFracBasisCond (line 13199) | func yearFracBasisCond(sy, sm, sd, ey, em, ed int) bool {
  function yearFracBasis0 (line 13205) | func yearFracBasis0(startDate, endDate float64) (dayDiff, daysInYear flo...
  function yearFracBasis1 (line 13228) | func yearFracBasis1(startDate, endDate float64) (dayDiff, daysInYear flo...
  function yearFracBasis4 (line 13257) | func yearFracBasis4(startDate, endDate float64) (dayDiff, daysInYear flo...
  function yearFrac (line 13274) | func yearFrac(startDate, endDate float64, basis int) formulaArg {
  function getYearDays (line 13301) | func getYearDays(year, basis int) int {
  function makeDate (line 13449) | func makeDate(y int, m time.Month, d int) int64 {
  function daysBetween (line 13459) | func daysBetween(startDate, endDate int64) float64 {
  function prepareToText (line 13601) | func prepareToText(name string, argsList *list.List) formulaArg {
  function bahttextAppendDigit (line 13657) | func bahttextAppendDigit(text string, digit int) string {
  function bahttextAppendPow10 (line 13665) | func bahttextAppendPow10(text string, digit, pow10 int) string {
  function bahttextAppendBlock (line 13681) | func bahttextAppendBlock(text string, val int) string {
  function textAfterBeforeSearch (line 14486) | func textAfterBeforeSearch(text string, delimiter []string, startPos int...
  function textAfterBeforeResult (line 14508) | func textAfterBeforeResult(name, modifiedDelimiter string, text []rune, ...
  function textJoin (line 14615) | func textJoin(arg *list.Element, arr []string, ignoreEmpty bool) ([]stri...
  function transposeFormulaArgsMatrix (line 14718) | func transposeFormulaArgsMatrix(args [][]formulaArg) [][]formulaArg {
  function transposeFormulaArgsList (line 14736) | func transposeFormulaArgsList(args []formulaArg, cols, rows int) ([]form...
  function concatValues (line 14748) | func concatValues(args []formulaArg) string {
  type uniqueArgs (line 14758) | type uniqueArgs struct
  function getFormulaUniqueArgs (line 14768) | func getFormulaUniqueArgs(argsList *list.List) (uniqueArgs, *formulaArg) {
  function matchPatternToRegExp (line 15050) | func matchPatternToRegExp(findText string, dbcs bool) (string, bool) {
  function matchPattern (line 15081) | func matchPattern(findText, withinText string, dbcs bool, startNum int) ...
  function compareFormulaArg (line 15105) | func compareFormulaArg(lhs, rhs, matchMode formulaArg, caseSensitive boo...
  function compareFormulaArgList (line 15142) | func compareFormulaArgList(lhs, rhs, matchMode formulaArg, caseSensitive...
  function compareFormulaArgMatrix (line 15160) | func compareFormulaArgMatrix(lhs, rhs, matchMode formulaArg, caseSensiti...
  function calcColsRowsMinMax (line 15208) | func calcColsRowsMinMax(cols bool, argsList *list.List) (minVal, maxVal ...
  function checkHVLookupArgs (line 15289) | func checkHVLookupArgs(name string, argsList *list.List) (idx int, looku...
  function calcMatchMatrix (line 15374) | func calcMatchMatrix(vertical bool, matchType int, criteria *formulaCrit...
  function calcMatch (line 15423) | func calcMatch(matchType int, criteria *formulaCriteria, lookupArray []f...
  function lookupLinearSearch (line 15534) | func lookupLinearSearch(vertical bool, lookupValue, lookupArray, matchMo...
  function lookupBinarySearch (line 15610) | func lookupBinarySearch(vertical bool, lookupValue, lookupArray, matchMo...
  function checkLookupArgs (line 15660) | func checkLookupArgs(argsList *list.List) (arrayForm bool, lookupValue, ...
  function iterateLookupArgs (line 15684) | func iterateLookupArgs(lookupValue, lookupVector formulaArg) ([]formulaA...
  function validateMatchMode (line 15741) | func validateMatchMode(mode float64) bool {
  function validateSearchMode (line 15747) | func validateSearchMode(mode float64) bool {
  function lookupCol (line 16002) | func lookupCol(arr formulaArg, idx int) []formulaArg {
  function validateFrequency (line 16078) | func validateFrequency(freq float64) bool {
  function is30BasisMethod (line 16326) | func is30BasisMethod(basis int) bool {
  function getDaysInMonthRange (line 16332) | func getDaysInMonthRange(fromMonth, toMonth int) int {
  function getDayOnBasis (line 16340) | func getDayOnBasis(y, m, d, basis int) int {
  function coupdays (line 16354) | func coupdays(from, to time.Time, basis int) float64 {
  function calcDbArgsCompare (line 16583) | func calcDbArgsCompare(cost, salvage, life, period formulaArg) bool {
  function calcIpmt (line 17156) | func calcIpmt(name string, typ, per, pmt, pv, rate formulaArg) formulaArg {
  function aggrBetween (line 17476) | func aggrBetween(startPeriod, endPeriod float64, initialValue []float64,...
  function fold (line 17491) | func fold(f func(acc []float64, index float64) []float64, state []float6...
  function changeMonth (line 17500) | func changeMonth(date time.Time, numMonths float64, returnLastMonth bool...
  function datesAggregate (line 17515) | func datesAggregate(startDate, endDate time.Time, numMonths float64, f f...
  function coupNumber (line 17539) | func coupNumber(maturity, settlement, numMonths float64) float64 {
  function prepareOddYldOrPrArg (line 17563) | func prepareOddYldOrPrArg(name string, arg formulaArg) formulaArg {
  function getODDFPRICE (line 17757) | func getODDFPRICE(f func(yld float64) float64, x, cnt, prec float64) flo...
  function checkPriceYieldArgs (line 18064) | func checkPriceYieldArgs(name string, rate, prYld, redemption, frequency...
  function xirrPart1 (line 18744) | func xirrPart1(values, dates []float64, rate float64) float64 {
  function xirrPart2 (line 18756) | func xirrPart2(values, dates []float64, rate float64) float64 {
  type calcDatabase (line 18966) | type calcDatabase struct
    method columnIndex (line 18997) | func (db *calcDatabase) columnIndex(database [][]formulaArg, field for...
    method criteriaEval (line 19011) | func (db *calcDatabase) criteriaEval() bool {
    method value (line 19043) | func (db *calcDatabase) value() formulaArg {
    method next (line 19051) | func (db *calcDatabase) next() bool {
  function newCalcDatabase (line 18975) | func newCalcDatabase(database, field, criteria formulaArg) *calcDatabase {
  type sortbyArgs (line 19271) | type sortbyArgs struct
  type sortbyKey (line 19279) | type sortbyKey struct
  type rowWithKeys (line 19287) | type rowWithKeys struct
  function checkSortbyArgs (line 19320) | func checkSortbyArgs(argsList *list.List) formulaArg {
  function prepareSortbyArgs (line 19342) | func prepareSortbyArgs(argsList *list.List) (sortbyArgs, *formulaArg) {
  function parseSortOrderArg (line 19393) | func parseSortOrderArg(byArray *list.Element, key *sortbyKey, keyCount, ...
  function compareRowsForSortby (line 19426) | func compareRowsForSortby(i, j rowWithKeys, sortKeys []sortbyKey) bool {

FILE: calc_test.go
  function prepareCalcData (line 14) | func prepareCalcData(cellData [][]interface{}) *File {
  function TestCalcCellValue (line 25) | func TestCalcCellValue(t *testing.T) {
  function TestCalcWithDefinedName (line 4765) | func TestCalcWithDefinedName(t *testing.T) {
  function TestCalcISBLANK (line 4826) | func TestCalcISBLANK(t *testing.T) {
  function TestCalcAND (line 4837) | func TestCalcAND(t *testing.T) {
  function TestCalcOR (line 4848) | func TestCalcOR(t *testing.T) {
  function TestCalcDet (line 4859) | func TestCalcDet(t *testing.T) {
  function TestCalcToBool (line 4868) | func TestCalcToBool(t *testing.T) {
  function TestCalcToList (line 4874) | func TestCalcToList(t *testing.T) {
  function TestCalcCompareFormulaArg (line 4880) | func TestCalcCompareFormulaArg(t *testing.T) {
  function TestCalcCompareFormulaArgMatrix (line 4898) | func TestCalcCompareFormulaArgMatrix(t *testing.T) {
  function TestCalcANCHORARRAY (line 4912) | func TestCalcANCHORARRAY(t *testing.T) {
  function TestCalcArrayFormula (line 4962) | func TestCalcArrayFormula(t *testing.T) {
  function TestCalcTRANSPOSE (line 5025) | func TestCalcTRANSPOSE(t *testing.T) {
  function TestCalcVLOOKUP (line 5040) | func TestCalcVLOOKUP(t *testing.T) {
  function TestCalcBoolean (line 5082) | func TestCalcBoolean(t *testing.T) {
  function TestCalcMAXMIN (line 5108) | func TestCalcMAXMIN(t *testing.T) {
  function TestCalcAVERAGEIF (line 5125) | func TestCalcAVERAGEIF(t *testing.T) {
  function TestCalcCOVAR (line 5156) | func TestCalcCOVAR(t *testing.T) {
  function TestCalcUniqueExactlyOnce (line 5199) | func TestCalcUniqueExactlyOnce(t *testing.T) {
  function TestCalcUniqueMultiColumn (line 5229) | func TestCalcUniqueMultiColumn(t *testing.T) {
  function TestCalcUniqueErrors (line 5254) | func TestCalcUniqueErrors(t *testing.T) {
  function TestTransposeFormulaArgsMatrix (line 5275) | func TestTransposeFormulaArgsMatrix(t *testing.T) {
  function TestGetFormulaUniqueArgs (line 5279) | func TestGetFormulaUniqueArgs(t *testing.T) {
  function TestCalcDatabase (line 5293) | func TestCalcDatabase(t *testing.T) {
  function TestCalcDBCS (line 5385) | func TestCalcDBCS(t *testing.T) {
  function TestCalcFORMULATEXT (line 5393) | func TestCalcFORMULATEXT(t *testing.T) {
  function TestCalcGROWTHandTREND (line 5404) | func TestCalcGROWTHandTREND(t *testing.T) {
  function TestCalcHLOOKUP (line 5482) | func TestCalcHLOOKUP(t *testing.T) {
  function TestCalcCHITESTandCHISQdotTEST (line 5521) | func TestCalcCHITESTandCHISQdotTEST(t *testing.T) {
  function TestCalcFTEST (line 5568) | func TestCalcFTEST(t *testing.T) {
  function TestCalcIRR (line 5613) | func TestCalcIRR(t *testing.T) {
  function TestCalcMAXMINIFS (line 5641) | func TestCalcMAXMINIFS(t *testing.T) {
  function TestCalcMIRR (line 5665) | func TestCalcMIRR(t *testing.T) {
  function TestCalcSUMIFSAndAVERAGEIFS (line 5691) | func TestCalcSUMIFSAndAVERAGEIFS(t *testing.T) {
  function TestCalcSUMIFExactMatch (line 5742) | func TestCalcSUMIFExactMatch(t *testing.T) {
  function TestCalcXIRR (line 5805) | func TestCalcXIRR(t *testing.T) {
  function TestCalcXLOOKUP (line 5843) | func TestCalcXLOOKUP(t *testing.T) {
  function TestCalcXNPV (line 5950) | func TestCalcXNPV(t *testing.T) {
  function TestCalcMATCH (line 5992) | func TestCalcMATCH(t *testing.T) {
  function TestCalcISFORMULA (line 6035) | func TestCalcISFORMULA(t *testing.T) {
  function TestCalcMODE (line 6046) | func TestCalcMODE(t *testing.T) {
  function TestCalcPEARSON (line 6092) | func TestCalcPEARSON(t *testing.T) {
  function TestCalcPROB (line 6129) | func TestCalcPROB(t *testing.T) {
  function TestCalcRSQ (line 6165) | func TestCalcRSQ(t *testing.T) {
  function TestCalcSLOP (line 6189) | func TestCalcSLOP(t *testing.T) {
  function TestCalcSHEET (line 6211) | func TestCalcSHEET(t *testing.T) {
  function TestCalcSHEETS (line 6228) | func TestCalcSHEETS(t *testing.T) {
  function TestCalcSTEY (line 6244) | func TestCalcSTEY(t *testing.T) {
  function TestCalcTTEST (line 6280) | func TestCalcTTEST(t *testing.T) {
  function TestCalcNETWORKDAYSandWORKDAY (line 6350) | func TestCalcNETWORKDAYSandWORKDAY(t *testing.T) {
  function TestCalcZTEST (line 6458) | func TestCalcZTEST(t *testing.T) {
  function TestStrToDate (line 6477) | func TestStrToDate(t *testing.T) {
  function TestGetYearDays (line 6482) | func TestGetYearDays(t *testing.T) {
  function TestCalcGetBetaHelperContFrac (line 6488) | func TestCalcGetBetaHelperContFrac(t *testing.T) {
  function TestCalcGetBetaDistPDF (line 6492) | func TestCalcGetBetaDistPDF(t *testing.T) {
  function TestCalcD1mach (line 6497) | func TestCalcD1mach(t *testing.T) {
  function TestCalcChebyshevInit (line 6501) | func TestCalcChebyshevInit(t *testing.T) {
  function TestCalcChebyshevEval (line 6506) | func TestCalcChebyshevEval(t *testing.T) {
  function TestCalcLgammacor (line 6510) | func TestCalcLgammacor(t *testing.T) {
  function TestCalcLgammaerr (line 6516) | func TestCalcLgammaerr(t *testing.T) {
  function TestCalcLogBeta (line 6520) | func TestCalcLogBeta(t *testing.T) {
  function TestCalcBetainvProbIterator (line 6525) | func TestCalcBetainvProbIterator(t *testing.T) {
  function TestCalcRangeResolver (line 6529) | func TestCalcRangeResolver(t *testing.T) {
  function TestCalcBahttextAppendDigit (line 6580) | func TestCalcBahttextAppendDigit(t *testing.T) {
  function TestNestedFunctionsWithOperators (line 6584) | func TestNestedFunctionsWithOperators(t *testing.T) {
  function TestFormulaRawCellValueOption (line 6604) | func TestFormulaRawCellValueOption(t *testing.T) {
  function TestFormulaArgToToken (line 6644) | func TestFormulaArgToToken(t *testing.T) {
  function TestPrepareTrendGrowth (line 6655) | func TestPrepareTrendGrowth(t *testing.T) {
  function TestCalcColRowQRDecomposition (line 6663) | func TestCalcColRowQRDecomposition(t *testing.T) {
  function TestCalcCellResolver (line 6668) | func TestCalcCellResolver(t *testing.T) {
  function TestEvalInfixExp (line 6731) | func TestEvalInfixExp(t *testing.T) {
  function TestParseToken (line 6740) | func TestParseToken(t *testing.T) {
  function TestCalcCellValueCache (line 6747) | func TestCalcCellValueCache(t *testing.T) {
  function TestCalcLookupCol (line 6849) | func TestCalcLookupCol(t *testing.T) {
  function TestCalcLookupLinearSearch (line 6864) | func TestCalcLookupLinearSearch(t *testing.T) {
  function TestCalcMatchMatrix (line 6879) | func TestCalcMatchMatrix(t *testing.T) {
  function TestCalcSORTBY (line 6892) | func TestCalcSORTBY(t *testing.T) {
  function TestCalcTrendGrowthMultipleRegressionPart2 (line 7012) | func TestCalcTrendGrowthMultipleRegressionPart2(t *testing.T) {
  function TestCalcTrendGrowthRegression (line 7027) | func TestCalcTrendGrowthRegression(t *testing.T) {
  function TestCalcImplicitIntersect (line 7032) | func TestCalcImplicitIntersect(t *testing.T) {

FILE: calcchain.go
  method calcChainReader (line 22) | func (f *File) calcChainReader() (*xlsxCalcChain, error) {
  method calcChainWriter (line 35) | func (f *File) calcChainWriter() {
  method deleteCalcChain (line 44) | func (f *File) deleteCalcChain(index int, cell string) error {
  type xlsxCalcChainCollection (line 72) | type xlsxCalcChainCollection
    method Filter (line 75) | func (c xlsxCalcChainCollection) Filter(fn func(v xlsxCalcChainC) bool...
  method volatileDepsReader (line 87) | func (f *File) volatileDepsReader() (*xlsxVolTypes, error) {
  method volatileDepsWriter (line 104) | func (f *File) volatileDepsWriter() {
  method deleteVolTopicRef (line 113) | func (vt *xlsxVolTypes) deleteVolTopicRef(i1, i2, i3, i4 int) {

FILE: calcchain_test.go
  function TestCalcChainReader (line 9) | func TestCalcChainReader(t *testing.T) {
  function TestDeleteCalcChain (line 18) | func TestDeleteCalcChain(t *testing.T) {

FILE: cell.go
  type CellType (line 29) | type CellType
  constant CellTypeUnset (line 33) | CellTypeUnset CellType = iota
  constant CellTypeBool (line 34) | CellTypeBool
  constant CellTypeDate (line 35) | CellTypeDate
  constant CellTypeError (line 36) | CellTypeError
  constant CellTypeFormula (line 37) | CellTypeFormula
  constant CellTypeInlineString (line 38) | CellTypeInlineString
  constant CellTypeNumber (line 39) | CellTypeNumber
  constant CellTypeSharedString (line 40) | CellTypeSharedString
  constant STCellFormulaTypeArray (line 45) | STCellFormulaTypeArray = "array"
  constant STCellFormulaTypeDataTable (line 47) | STCellFormulaTypeDataTable = "dataTable"
  constant STCellFormulaTypeNormal (line 49) | STCellFormulaTypeNormal = "normal"
  constant STCellFormulaTypeShared (line 51) | STCellFormulaTypeShared = "shared"
  method GetCellValue (line 71) | func (f *File) GetCellValue(sheet, cell string, opts ...Options) (string...
  method GetCellType (line 84) | func (f *File) GetCellType(sheet, cell string) (CellType, error) {
  method SetCellValue (line 129) | func (f *File) SetCellValue(sheet, cell string, value interface{}) error {
  method String (line 162) | func (x xlsxSI) String() string {
  method hasValue (line 179) | func (c *xlsxC) hasValue() bool {
  method removeFormula (line 184) | func (f *File) removeFormula(c *xlsxC, ws *xlsxWorksheet, sheet string) ...
  method setCellIntFunc (line 209) | func (f *File) setCellIntFunc(sheet, cell string, value interface{}) err...
  method setCellTimeFunc (line 238) | func (f *File) setCellTimeFunc(sheet, cell string, value time.Time) error {
  method setCellTime (line 269) | func (c *xlsxC) setCellTime(value time.Time, date1904 bool) (isNum bool,...
  function setCellDuration (line 287) | func setCellDuration(value time.Duration) (t string, v string) {
  method SetCellInt (line 294) | func (f *File) SetCellInt(sheet, cell string, value int64) error {
  function setCellInt (line 315) | func setCellInt(value int64) (t string, v string) {
  method SetCellUint (line 322) | func (f *File) SetCellUint(sheet, cell string, value uint64) error {
  function setCellUint (line 344) | func setCellUint(value uint64) (t string, v string) {
  method SetCellBool (line 351) | func (f *File) SetCellBool(sheet, cell string, value bool) error {
  function setCellBool (line 373) | func setCellBool(value bool) (t string, v string) {
  method SetCellFloat (line 391) | func (f *File) SetCellFloat(sheet, cell string, value float64, precision...
  method setCellFloat (line 415) | func (c *xlsxC) setCellFloat(value float64, precision, bitSize int) {
  method SetCellStr (line 426) | func (f *File) SetCellStr(sheet, cell, value string) error {
  method setCellString (line 449) | func (f *File) setCellString(value string) (t, v string, err error) {
  method sharedStringsLoader (line 464) | func (f *File) sharedStringsLoader() (err error) {
  method setSharedString (line 487) | func (f *File) setSharedString(val string) (int, error) {
  function trimCellValue (line 512) | func trimCellValue(value string, escape bool) (v string, ns xml.Attr) {
  method setCellValue (line 540) | func (c *xlsxC) setCellValue(val string) {
  method setInlineStr (line 550) | func (c *xlsxC) setInlineStr(val string) {
  method setStr (line 556) | func (c *xlsxC) setStr(val string) {
  method getCellBool (line 562) | func (c *xlsxC) getCellBool(f *File, raw bool) (string, error) {
  method setCellDefault (line 576) | func (c *xlsxC) setCellDefault(value string) {
  method getCellDate (line 590) | func (c *xlsxC) getCellDate(f *File, raw bool) (string, error) {
  method getValueFrom (line 612) | func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, err...
  method SetCellDefault (line 652) | func (f *File) SetCellDefault(sheet, cell, value string) error {
  method GetCellFormula (line 673) | func (f *File) GetCellFormula(sheet, cell string) (string, error) {
  method getCellFormula (line 679) | func (f *File) getCellFormula(sheet, cell string, transformed bool) (str...
  type FormulaOpts (line 702) | type FormulaOpts struct
  method SetCellFormula (line 789) | func (f *File) SetCellFormula(sheet, cell, formula string, opts ...Formu...
  method setArrayFormula (line 840) | func (ws *xlsxWorksheet) setArrayFormula(sheet string, formula *xlsxF, d...
  method setArrayFormulaCells (line 875) | func (f *File) setArrayFormulaCells() error {
  method setSharedFormula (line 899) | func (ws *xlsxWorksheet) setSharedFormula(cell, ref string) error {
  method countSharedFormula (line 927) | func (ws *xlsxWorksheet) countSharedFormula() (count int) {
  method deleteSharedFormula (line 941) | func (ws *xlsxWorksheet) deleteSharedFormula(c *xlsxC) {
  method GetCellHyperLink (line 963) | func (f *File) GetCellHyperLink(sheet, cell string) (bool, string, error) {
  method GetHyperLinkCells (line 994) | func (f *File) GetHyperLinkCells(sheet, linkType string) ([]string, erro...
  type HyperlinkOpts (line 1025) | type HyperlinkOpts struct
  method removeHyperLink (line 1033) | func (f *File) removeHyperLink(ws *xlsxWorksheet, sheet, cell string) er...
  method SetCellHyperLink (line 1081) | func (f *File) SetCellHyperLink(sheet, cell, link, linkType string, opts...
  function getCellRichText (line 1150) | func getCellRichText(si *xlsxSI) (runs []RichTextRun) {
  method GetCellRichText (line 1168) | func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, ...
  method newRpr (line 1200) | func (fnt *Font) newRpr() *xlsxRPr {
  method getFont (line 1222) | func (rPr *xlsxRPr) getFont() *Font {
  function setRichText (line 1243) | func setRichText(runs []RichTextRun) ([]xlsxR, error) {
  method SetCellRichText (line 1387) | func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) e...
  method SetSheetRow (line 1428) | func (f *File) SetSheetRow(sheet, cell string, slice interface{}) error {
  method SetSheetCol (line 1437) | func (f *File) SetSheetCol(sheet, cell string, slice interface{}) error {
  method setSheetCells (line 1442) | func (f *File) setSheetCells(sheet, cell string, slice interface{}, dir ...
  method prepareCell (line 1474) | func (ws *xlsxWorksheet) prepareCell(cell string) (*xlsxC, int, int, err...
  method getCellStringFunc (line 1492) | func (f *File) getCellStringFunc(sheet, cell string, fn func(x *xlsxWork...
  method formattedValue (line 1552) | func (f *File) formattedValue(c *xlsxC, raw bool, cellType CellType) (st...
  method getCustomNumFmtCode (line 1588) | func (ss *xlsxStyleSheet) getCustomNumFmtCode(numFmtID int) (string, boo...
  method prepareCellStyle (line 1605) | func (ws *xlsxWorksheet) prepareCellStyle(col, row, style int) int {
  method mergeCellsParser (line 1626) | func (ws *xlsxWorksheet) mergeCellsParser(cell string) (string, error) {
  method checkCellInRangeRef (line 1661) | func (f *File) checkCellInRangeRef(cell, rangeRef string) (bool, error) {
  function cellInRange (line 1680) | func cellInRange(cell, ref []int) bool {
  function isOverlap (line 1685) | func isOverlap(rect1, rect2 []int) bool {
  method convertSharedFormula (line 1698) | func (c *xlsxC) convertSharedFormula(cell string) (string, error) {
  function getSharedFormula (line 1727) | func getSharedFormula(ws *xlsxWorksheet, si int, cell string) (string, e...
  function shiftCell (line 1748) | func shiftCell(val string, dCol, dRow int) string {

FILE: cell_test.go
  function TestConcurrency (line 19) | func TestConcurrency(t *testing.T) {
  function TestCheckCellInRangeRef (line 119) | func TestCheckCellInRangeRef(t *testing.T) {
  function TestSetCellFloat (line 160) | func TestSetCellFloat(t *testing.T) {
  function TestSetCellUint (line 195) | func TestSetCellUint(t *testing.T) {
  function TestSetCellValuesMultiByte (line 215) | func TestSetCellValuesMultiByte(t *testing.T) {
  function TestSetCellValue (line 248) | func TestSetCellValue(t *testing.T) {
  function TestSetCellValues (line 333) | func TestSetCellValues(t *testing.T) {
  function TestSetCellBool (line 351) | func TestSetCellBool(t *testing.T) {
  function TestSetCellTime (line 358) | func TestSetCellTime(t *testing.T) {
  function TestGetCellValue (line 377) | func TestGetCellValue(t *testing.T) {
  function TestGetCellType (line 543) | func TestGetCellType(t *testing.T) {
  function TestGetValueFrom (line 559) | func TestGetValueFrom(t *testing.T) {
  function TestGetCellFormula (line 574) | func TestGetCellFormula(t *testing.T) {
  function TestConvertSharedFormula (line 704) | func TestConvertSharedFormula(t *testing.T) {
  function ExampleFile_SetCellFloat (line 712) | func ExampleFile_SetCellFloat() {
  function BenchmarkSetCellValue (line 732) | func BenchmarkSetCellValue(b *testing.B) {
  function TestOverflowNumericCell (line 746) | func TestOverflowNumericCell(t *testing.T) {
  function TestSetCellFormula (line 758) | func TestSetCellFormula(t *testing.T) {
  function TestGetCellRichText (line 825) | func TestGetCellRichText(t *testing.T) {
  function TestSetCellRichText (line 931) | func TestSetCellRichText(t *testing.T) {
  function TestFormattedValue (line 1040) | func TestFormattedValue(t *testing.T) {
  function TestFormattedValueNilXfs (line 1129) | func TestFormattedValueNilXfs(t *testing.T) {
  function TestFormattedValueNilNumFmts (line 1138) | func TestFormattedValueNilNumFmts(t *testing.T) {
  function TestFormattedValueNilWorkbook (line 1147) | func TestFormattedValueNilWorkbook(t *testing.T) {
  function TestFormattedValueNilWorkbookPr (line 1156) | func TestFormattedValueNilWorkbookPr(t *testing.T) {
  function TestGetCustomNumFmtCode (line 1166) | func TestGetCustomNumFmtCode(t *testing.T) {
  function TestSharedStringsError (line 1176) | func TestSharedStringsError(t *testing.T) {
  function TestSetCellIntFunc (line 1247) | func TestSetCellIntFunc(t *testing.T) {
  function TestSIString (line 1270) | func TestSIString(t *testing.T) {
  function TestGetCellStringFunc (line 1274) | func TestGetCellStringFunc(t *testing.T) {

FILE: chart.go
  type ChartType (line 22) | type ChartType
  constant Area (line 26) | Area ChartType = iota
  constant AreaStacked (line 27) | AreaStacked
  constant AreaPercentStacked (line 28) | AreaPercentStacked
  constant Area3D (line 29) | Area3D
  constant Area3DStacked (line 30) | Area3DStacked
  constant Area3DPercentStacked (line 31) | Area3DPercentStacked
  constant Bar (line 32) | Bar
  constant BarStacked (line 33) | BarStacked
  constant BarPercentStacked (line 34) | BarPercentStacked
  constant Bar3DClustered (line 35) | Bar3DClustered
  constant Bar3DStacked (line 36) | Bar3DStacked
  constant Bar3DPercentStacked (line 37) | Bar3DPercentStacked
  constant Bar3DConeClustered (line 38) | Bar3DConeClustered
  constant Bar3DConeStacked (line 39) | Bar3DConeStacked
  constant Bar3DConePercentStacked (line 40) | Bar3DConePercentStacked
  constant Bar3DPyramidClustered (line 41) | Bar3DPyramidClustered
  constant Bar3DPyramidStacked (line 42) | Bar3DPyramidStacked
  constant Bar3DPyramidPercentStacked (line 43) | Bar3DPyramidPercentStacked
  constant Bar3DCylinderClustered (line 44) | Bar3DCylinderClustered
  constant Bar3DCylinderStacked (line 45) | Bar3DCylinderStacked
  constant Bar3DCylinderPercentStacked (line 46) | Bar3DCylinderPercentStacked
  constant Col (line 47) | Col
  constant ColStacked (line 48) | ColStacked
  constant ColPercentStacked (line 49) | ColPercentStacked
  constant Col3D (line 50) | Col3D
  constant Col3DClustered (line 51) | Col3DClustered
  constant Col3DStacked (line 52) | Col3DStacked
  constant Col3DPercentStacked (line 53) | Col3DPercentStacked
  constant Col3DCone (line 54) | Col3DCone
  constant Col3DConeClustered (line 55) | Col3DConeClustered
  constant Col3DConeStacked (line 56) | Col3DConeStacked
  constant Col3DConePercentStacked (line 57) | Col3DConePercentStacked
  constant Col3DPyramid (line 58) | Col3DPyramid
  constant Col3DPyramidClustered (line 59) | Col3DPyramidClustered
  constant Col3DPyramidStacked (line 60) | Col3DPyramidStacked
  constant Col3DPyramidPercentStacked (line 61) | Col3DPyramidPercentStacked
  constant Col3DCylinder (line 62) | Col3DCylinder
  constant Col3DCylinderClustered (line 63) | Col3DCylinderClustered
  constant Col3DCylinderStacked (line 64) | Col3DCylinderStacked
  constant Col3DCylinderPercentStacked (line 65) | Col3DCylinderPercentStacked
  constant Doughnut (line 66) | Doughnut
  constant Line (line 67) | Line
  constant Line3D (line 68) | Line3D
  constant Pie (line 69) | Pie
  constant Pie3D (line 70) | Pie3D
  constant PieOfPie (line 71) | PieOfPie
  constant BarOfPie (line 72) | BarOfPie
  constant Radar (line 73) | Radar
  constant Scatter (line 74) | Scatter
  constant Surface3D (line 75) | Surface3D
  constant WireframeSurface3D (line 76) | WireframeSurface3D
  constant Contour (line 77) | Contour
  constant WireframeContour (line 78) | WireframeContour
  constant Bubble (line 79) | Bubble
  constant Bubble3D (line 80) | Bubble3D
  constant StockHighLowClose (line 81) | StockHighLowClose
  constant StockOpenHighLowClose (line 82) | StockOpenHighLowClose
  type ChartDashType (line 86) | type ChartDashType
  constant ChartDashUnset (line 90) | ChartDashUnset ChartDashType = iota
  constant ChartDashSolid (line 91) | ChartDashSolid
  constant ChartDashDot (line 92) | ChartDashDot
  constant ChartDashDash (line 93) | ChartDashDash
  constant ChartDashLgDash (line 94) | ChartDashLgDash
  constant ChartDashSashDot (line 95) | ChartDashSashDot
  constant ChartDashLgDashDot (line 96) | ChartDashLgDashDot
  constant ChartDashLgDashDotDot (line 97) | ChartDashLgDashDotDot
  constant ChartDashSysDash (line 98) | ChartDashSysDash
  constant ChartDashSysDot (line 99) | ChartDashSysDot
  constant ChartDashSysDashDot (line 100) | ChartDashSysDashDot
  constant ChartDashSysDashDotDot (line 101) | ChartDashSysDashDotDot
  type ChartLineType (line 105) | type ChartLineType
  constant ChartLineUnset (line 109) | ChartLineUnset ChartLineType = iota
  constant ChartLineSolid (line 110) | ChartLineSolid
  constant ChartLineNone (line 111) | ChartLineNone
  constant ChartLineAutomatic (line 112) | ChartLineAutomatic
  type ChartTickLabelPositionType (line 117) | type ChartTickLabelPositionType
  constant ChartTickLabelNextToAxis (line 122) | ChartTickLabelNextToAxis ChartTickLabelPositionType = iota
  constant ChartTickLabelHigh (line 123) | ChartTickLabelHigh
  constant ChartTickLabelLow (line 124) | ChartTickLabelLow
  constant ChartTickLabelNone (line 125) | ChartTickLabelNone
  function parseChartOptions (line 576) | func parseChartOptions(opts *Chart) (*Chart, error) {
  method parseSeries (line 612) | func (opts *Chart) parseSeries() error {
  method parseTitle (line 622) | func (opts *Chart) parseTitle() {
  method AddChart (line 1190) | func (f *File) AddChart(sheet, cell string, chart *Chart, combo ...*Char...
  method AddChartSheet (line 1224) | func (f *File) AddChartSheet(sheet string, chart *Chart, combo ...*Chart...
  method getChartOptions (line 1281) | func (f *File) getChartOptions(opts *Chart, combo []*Chart) (*Chart, []*...
  method DeleteChart (line 1305) | func (f *File) DeleteChart(sheet, cell string) error {
  method countCharts (line 1326) | func (f *File) countCharts() int {
  method ptToEMUs (line 1340) | func (f *File) ptToEMUs(pt float64) int {

FILE: chart_test.go
  function TestChartSize (line 13) | func TestChartSize(t *testing.T) {
  function TestAddDrawingChart (line 100) | func TestAddDrawingChart(t *testing.T) {
  function TestAddSheetDrawingChart (line 109) | func TestAddSheetDrawingChart(t *testing.T) {
  function TestDeleteDrawing (line 116) | func TestDeleteDrawing(t *testing.T) {
  function TestAddChart (line 136) | func TestAddChart(t *testing.T) {
  function TestAddChartSheet (line 449) | func TestAddChartSheet(t *testing.T) {
  function TestDeleteChart (line 495) | func TestDeleteChart(t *testing.T) {
  function TestChartWithLogarithmicBase (line 543) | func TestChartWithLogarithmicBase(t *testing.T) {

FILE: col.go
  type Cols (line 26) | type Cols struct
    method Next (line 71) | func (cols *Cols) Next() bool {
    method Error (line 77) | func (cols *Cols) Error() error {
    method Rows (line 82) | func (cols *Cols) Rows(opts ...Options) ([]string, error) {
    method rowXMLHandler (line 160) | func (cols *Cols) rowXMLHandler(rowIterator *rowXMLIterator, xmlElemen...
  method GetCols (line 57) | func (f *File) GetCols(sheet string, opts ...Options) ([][]string, error) {
  type columnXMLIterator (line 121) | type columnXMLIterator struct
  function columnXMLHandler (line 128) | func columnXMLHandler(colIterator *columnXMLIterator, xmlElement *xml.St...
  method Cols (line 202) | func (f *File) Cols(sheet string) (*Cols, error) {
  method GetColVisible (line 247) | func (f *File) GetColVisible(sheet, col string) (bool, error) {
  method SetColVisible (line 284) | func (f *File) SetColVisible(sheet, columns string, visible bool) error {
  method setColVisible (line 301) | func (ws *xlsxWorksheet) setColVisible(minVal, maxVal int, visible bool) {
  method GetColOutlineLevel (line 332) | func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
  method parseColRange (line 355) | func (f *File) parseColRange(columns string) (minVal, maxVal int, err er...
  method SetColOutlineLevel (line 378) | func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
  method setColOutlineLevel (line 396) | func (ws *xlsxWorksheet) setColOutlineLevel(colNum int, level uint8) {
  method SetColStyle (line 433) | func (f *File) SetColStyle(sheet, columns string, styleID int) error {
  method setColStyle (line 471) | func (ws *xlsxWorksheet) setColStyle(minVal, maxVal, styleID int) {
  method SetColWidth (line 500) | func (f *File) SetColWidth(sheet, startCol, endCol string, width float64...
  method setColWidth (line 523) | func (ws *xlsxWorksheet) setColWidth(minVal, maxVal int, width float64) {
  function flatCols (line 549) | func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) ...
  method positionObjectPixels (line 628) | func (f *File) positionObjectPixels(sheet string, col, row, width, heigh...
  method getColWidth (line 661) | func (f *File) getColWidth(sheet string, col int) int {
  method GetColStyle (line 691) | func (f *File) GetColStyle(sheet, col string) (int, error) {
  method GetColWidth (line 718) | func (f *File) GetColWidth(sheet, col string) (float64, error) {
  method InsertCols (line 765) | func (f *File) InsertCols(sheet, col string, n int) error {
  method RemoveCol (line 785) | func (f *File) RemoveCol(sheet, col string) error {
  function convertColWidthToPixels (line 813) | func convertColWidthToPixels(width float64) float64 {
  method calcTextWidth (line 825) | func (fnt *Font) calcTextWidth(text string) float64 {
  method calcRichTextWidth (line 862) | func (fnt *Font) calcRichTextWidth(runs []RichTextRun) float64 {
  method autoFitColWidth (line 887) | func (f *File) autoFitColWidth(sheet string, col, rows int, defaultFnt *...
  method AutoFitColWidth (line 952) | func (f *File) AutoFitColWidth(sheet, columns string) error {

FILE: col_test.go
  function TestCols (line 15) | func TestCols(t *testing.T) {
  function TestColumnsIterator (line 91) | func TestColumnsIterator(t *testing.T) {
  function TestColsError (line 121) | func TestColsError(t *testing.T) {
  function TestGetColsError (line 131) | func TestGetColsError(t *testing.T) {
  function TestColsRows (line 167) | func TestColsRows(t *testing.T) {
  function TestColumnVisibility (line 200) | func TestColumnVisibility(t *testing.T) {
  function TestOutlineLevel (line 265) | func TestOutlineLevel(t *testing.T) {
  function TestSetColStyle (line 334) | func TestSetColStyle(t *testing.T) {
  function TestColWidth (line 383) | func TestColWidth(t *testing.T) {
  function TestGetColStyle (line 423) | func TestGetColStyle(t *testing.T) {
  function TestInsertCols (line 440) | func TestInsertCols(t *testing.T) {
  function TestRemoveCol (line 463) | func TestRemoveCol(t *testing.T) {
  function TestConvertColWidthToPixels (line 488) | func TestConvertColWidthToPixels(t *testing.T) {
  function TestAutoFitColWidth (line 492) | func TestAutoFitColWidth(t *testing.T) {

FILE: crypt.go
  type Encryption (line 55) | type Encryption struct
  type KeyData (line 63) | type KeyData struct
  type DataIntegrity (line 77) | type DataIntegrity struct
  type KeyEncryptors (line 83) | type KeyEncryptors struct
  type KeyEncryptor (line 89) | type KeyEncryptor struct
  type EncryptedKey (line 96) | type EncryptedKey struct
  type StandardEncryptionHeader (line 108) | type StandardEncryptionHeader struct
  type StandardEncryptionVerifier (line 124) | type StandardEncryptionVerifier struct
  type encryption (line 134) | type encryption struct
    method encrypt (line 339) | func (e *encryption) encrypt(input []byte) []byte {
    method standardKeyEncryption (line 361) | func (e *encryption) standardKeyEncryption(password string) ([]byte, e...
  function Decrypt (line 143) | func Decrypt(raw []byte, opts *Options) (packageBuf []byte, err error) {
  function Encrypt (line 163) | func Encrypt(raw []byte, opts *Options) ([]byte, error) {
  function extractPart (line 192) | func extractPart(doc *mscfb.Reader) ([]byte, []byte, error) {
  function encryptionMechanism (line 214) | func encryptionMechanism(buffer []byte) (mechanism string, err error) {
  function standardDecrypt (line 236) | func standardDecrypt(encryptionInfoBuf, encryptedPackageBuf []byte, opts...
  function standardEncryptionVerifier (line 281) | func standardEncryptionVerifier(algorithm string, blob []byte) StandardE...
  function standardConvertPasswdToKey (line 298) | func standardConvertPasswdToKey(header StandardEncryptionHeader, verifie...
  function standardXORBytes (line 325) | func standardXORBytes(a, b []byte) []byte {
  function agileDecrypt (line 404) | func agileDecrypt(encryptionInfoBuf, encryptedPackageBuf []byte, opts *O...
  function convertPasswdToKey (line 430) | func convertPasswdToKey(passwd string, blockKey []byte, encryption Encry...
  function hashing (line 464) | func hashing(hashAlgorithm string, buffer ...[]byte) (key []byte) {
  function createUInt32LEBuffer (line 487) | func createUInt32LEBuffer(value int, bufferSize int) []byte {
  function parseEncryptionInfo (line 494) | func parseEncryptionInfo(encryptionInfo []byte) (encryption Encryption, ...
  function decrypt (line 501) | func decrypt(key, iv, input []byte) (packageKey []byte, err error) {
  function decryptPackage (line 512) | func decryptPackage(packageKey, input []byte, encryption Encryption) (ou...
  function createIV (line 553) | func createIV(blockKey interface{}, encryption Encryption) ([]byte, erro...
  function randomBytes (line 581) | func randomBytes(n int) ([]byte, error) {
  function genISOPasswdHash (line 592) | func genISOPasswdHash(passwd, hashAlgorithm, salt string, spinCount int)...
  type cfb (line 634) | type cfb struct
    method writeBytes (line 649) | func (c *cfb) writeBytes(value []byte) {
    method writeUint16 (line 662) | func (c *cfb) writeUint16(value int) {
    method writeUint32 (line 670) | func (c *cfb) writeUint32(value int) {
    method writeUint64 (line 678) | func (c *cfb) writeUint64(value int) {
    method writeStrings (line 685) | func (c *cfb) writeStrings(value string) {
    method put (line 696) | func (c *cfb) put(name string, content []byte) {
    method compare (line 715) | func (c *cfb) compare(left, right string) int {
    method prepare (line 732) | func (c *cfb) prepare() {
    method locate (line 777) | func (c *cfb) locate() []int {
    method writeMSAT (line 819) | func (c *cfb) writeMSAT(location []int) {
    method writeDirectoryEntry (line 852) | func (c *cfb) writeDirectoryEntry(location []int) {
    method writeSectorChains (line 909) | func (c *cfb) writeSectorChains(location []int) sector {
    method write (line 962) | func (c *cfb) write() []byte {
  type sector (line 642) | type sector struct

FILE: crypt_test.go
  function TestEncrypt (line 27) | func TestEncrypt(t *testing.T) {
  function TestEncryptionMechanism (line 195) | func TestEncryptionMechanism(t *testing.T) {
  function TestHashing (line 203) | func TestHashing(t *testing.T) {
  function TestGenISOPasswdHash (line 207) | func TestGenISOPasswdHash(t *testing.T) {

FILE: datavalidation.go
  type DataValidationType (line 24) | type DataValidationType
  constant _ (line 28) | _ DataValidationType = iota
  constant DataValidationTypeNone (line 29) | DataValidationTypeNone
  constant DataValidationTypeCustom (line 30) | DataValidationTypeCustom
  constant DataValidationTypeDate (line 31) | DataValidationTypeDate
  constant DataValidationTypeDecimal (line 32) | DataValidationTypeDecimal
  constant DataValidationTypeList (line 33) | DataValidationTypeList
  constant DataValidationTypeTextLength (line 34) | DataValidationTypeTextLength
  constant DataValidationTypeTime (line 35) | DataValidationTypeTime
  constant DataValidationTypeWhole (line 36) | DataValidationTypeWhole
  type DataValidationErrorStyle (line 40) | type DataValidationErrorStyle
  constant _ (line 44) | _ DataValidationErrorStyle = iota
  constant DataValidationErrorStyleStop (line 45) | DataValidationErrorStyleStop
  constant DataValidationErrorStyleWarning (line 46) | DataValidationErrorStyleWarning
  constant DataValidationErrorStyleInformation (line 47) | DataValidationErrorStyleInformation
  constant styleStop (line 52) | styleStop        = "stop"
  constant styleWarning (line 53) | styleWarning     = "warning"
  constant styleInformation (line 54) | styleInformation = "information"
  type DataValidationOperator (line 58) | type DataValidationOperator
  constant _ (line 62) | _ DataValidationOperator = iota
  constant DataValidationOperatorBetween (line 63) | DataValidationOperatorBetween
  constant DataValidationOperatorEqual (line 64) | DataValidationOperatorEqual
  constant DataValidationOperatorGreaterThan (line 65) | DataValidationOperatorGreaterThan
  constant DataValidationOperatorGreaterThanOrEqual (line 66) | DataValidationOperatorGreaterThanOrEqual
  constant DataValidationOperatorLessThan (line 67) | DataValidationOperatorLessThan
  constant DataValidationOperatorLessThanOrEqual (line 68) | DataValidationOperatorLessThanOrEqual
  constant DataValidationOperatorNotBetween (line 69) | DataValidationOperatorNotBetween
  constant DataValidationOperatorNotEqual (line 70) | DataValidationOperatorNotEqual
  function NewDataValidation (line 111) | func NewDataValidation(allowBlank bool) *DataValidation {
  method SetError (line 120) | func (dv *DataValidation) SetError(style DataValidationErrorStyle, title...
  method SetInput (line 138) | func (dv *DataValidation) SetInput(title, msg string) {
  method SetDropList (line 150) | func (dv *DataValidation) SetDropList(keys []string) error {
  method SetRange (line 166) | func (dv *DataValidation) SetRange(f1, f2 interface{}, t DataValidationT...
  method SetSqrefDropList (line 212) | func (dv *DataValidation) SetSqrefDropList(sqref string) {
  method SetSqref (line 218) | func (dv *DataValidation) SetSqref(sqref string) {
  method AddDataValidation (line 257) | func (f *File) AddDataValidation(sheet string, dv *DataValidation) error {
  method GetDataValidations (line 293) | func (f *File) GetDataValidations(sheet string) ([]*DataValidation, erro...
  function getDataValidations (line 325) | func getDataValidations(dvs *xlsxDataValidations) []*DataValidation {
  method DeleteDataValidation (line 386) | func (f *File) DeleteDataValidation(sheet string, sqref ...string) error {
  method deleteDataValidation (line 417) | func (f *File) deleteDataValidation(ws *xlsxWorksheet, delCells map[int]...
  method deleteX14DataValidation (line 438) | func (f *File) deleteX14DataValidation(ws *xlsxWorksheet, delCells map[i...
  function squashSqref (line 500) | func squashSqref(cells [][]int) []string {
  function deleteCellsFromSqref (line 530) | func deleteCellsFromSqref(sqref string, delCells map[int][][]int) (strin...
  method isFormula (line 554) | func (dv *xlsxInnerXML) isFormula() bool {
  function unescapeDataValidationFormula (line 559) | func unescapeDataValidationFormula(val string) string {

FILE: datavalidation_test.go
  function TestDataValidation (line 25) | func TestDataValidation(t *testing.T) {
  function TestDataValidationError (line 136) | func TestDataValidationError(t *testing.T) {
  function TestDeleteDataValidation (line 200) | func TestDeleteDataValidation(t *testing.T) {

FILE: date.go
  constant nanosInADay (line 20) | nanosInADay    = float64((24 * time.Hour) / time.Nanosecond)
  constant dayNanoseconds (line 21) | dayNanoseconds = 24 * time.Hour
  constant maxDuration (line 22) | maxDuration    = 290 * 364 * dayNanoseconds
  constant roundEpsilon (line 23) | roundEpsilon   = 1e-9
  function timeToExcelTime (line 35) | func timeToExcelTime(t time.Time, date1904 bool) (float64, error) {
  function shiftJulianToNoon (line 65) | func shiftJulianToNoon(julianDays, julianFraction float64) (float64, flo...
  function fractionOfADay (line 82) | func fractionOfADay(fraction float64) (hours, minutes, seconds, nanoseco...
  function julianDateToGregorianTime (line 101) | func julianDateToGregorianTime(part1, part2 float64) time.Time {
  function doTheFliegelAndVanFlandernAlgorithm (line 119) | func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
  function timeFromExcelTime (line 135) | func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
  function ExcelDateToTime (line 167) | func ExcelDateToTime(excelDate float64, use1904Format bool) (time.Time, ...
  function isLeapYear (line 175) | func isLeapYear(y int) bool {
  function getDaysInMonth (line 187) | func getDaysInMonth(y, m int) int {
  function validateDate (line 196) | func validateDate(y, m, d int) bool {
  function formatYear (line 207) | func formatYear(y int) int {
  function getDurationNumFmt (line 220) | func getDurationNumFmt(d time.Duration) int {
  function getTimeNumFmt (line 233) | func getTimeNumFmt(t time.Time) int {

FILE: date_test.go
  type dateTest (line 11) | type dateTest struct
  function TestTimeToExcelTime (line 40) | func TestTimeToExcelTime(t *testing.T) {
  function TestTimeToExcelTime_Timezone (line 51) | func TestTimeToExcelTime_Timezone(t *testing.T) {
  function TestTimeFromExcelTime (line 64) | func TestTimeFromExcelTime(t *testing.T) {
  function TestTimeFromExcelTime_1904 (line 93) | func TestTimeFromExcelTime_1904(t *testing.T) {
  function TestExcelDateToTime (line 104) | func TestExcelDateToTime(t *testing.T) {

FILE: docProps.go
  method SetAppProps (line 69) | func (f *File) SetAppProps(appProperties *AppProperties) error {
  method GetAppProps (line 84) | func (f *File) GetAppProps() (ret *AppProperties, err error) {
  method SetDocProps (line 165) | func (f *File) SetDocProps(docProperties *DocProperties) error {
  method GetDocProps (line 212) | func (f *File) GetDocProps() (ret *DocProperties, err error) {
  method SetCustomProps (line 248) | func (f *File) SetCustomProps(prop CustomProperty) error {
  method setCustomProps (line 296) | func (prop *xlsxProperty) setCustomProps(value interface{}) error {
  method GetCustomProps (line 315) | func (f *File) GetCustomProps() ([]CustomProperty, error) {
  method getCustomProps (line 334) | func (p *decodeProperty) getCustomProps() (interface{}, error) {

FILE: docProps_test.go
  function TestSetAppProps (line 26) | func TestSetAppProps(t *testing.T) {
  function TestGetAppProps (line 51) | func TestGetAppProps(t *testing.T) {
  function TestSetDocProps (line 71) | func TestSetDocProps(t *testing.T) {
  function TestGetDocProps (line 103) | func TestGetDocProps(t *testing.T) {
  function TestCustomProps (line 123) | func TestCustomProps(t *testing.T) {

FILE: drawing.go
  method prepareDrawing (line 25) | func (f *File) prepareDrawing(ws *xlsxWorksheet, drawingID int, sheet, d...
  method prepareChartSheetDrawing (line 45) | func (f *File) prepareChartSheetDrawing(cs *xlsxChartsheet, drawingID in...
  method addChart (line 59) | func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
  method drawBaseChart (line 201) | func (f *File) drawBaseChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawDoughnutChart (line 447) | func (f *File) drawDoughnutChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawLineChart (line 468) | func (f *File) drawLineChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawLine3DChart (line 497) | func (f *File) drawLine3DChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawPieChart (line 523) | func (f *File) drawPieChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawPie3DChart (line 538) | func (f *File) drawPie3DChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawPieOfPieChart (line 553) | func (f *File) drawPieOfPieChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawBarOfPieChart (line 577) | func (f *File) drawBarOfPieChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawRadarChart (line 601) | func (f *File) drawRadarChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawScatterChart (line 623) | func (f *File) drawScatterChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawSurface3DChart (line 644) | func (f *File) drawSurface3DChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawSurfaceChart (line 668) | func (f *File) drawSurfaceChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawBubbleChart (line 692) | func (f *File) drawBubbleChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawStockChart (line 714) | func (f *File) drawStockChart(pa *cPlotArea, opts *Chart) *cPlotArea {
  method drawChartGapWidth (line 747) | func (f *File) drawChartGapWidth(opts *Chart) *attrValInt {
  method drawChartOverlap (line 758) | func (f *File) drawChartOverlap(opts *Chart) *attrValInt {
  method drawChartShape (line 776) | func (f *File) drawChartShape(opts *Chart) *attrValString {
  method drawChartSeries (line 808) | func (f *File) drawChartSeries(opts *Chart) *[]cSer {
  method drawShapeFill (line 838) | func (f *File) drawShapeFill(fill Fill, spPr *cSpPr) *cSpPr {
  method drawChartSeriesSpPr (line 859) | func (f *File) drawChartSeriesSpPr(i int, opts *Chart) *cSpPr {
  method drawChartSeriesDPt (line 889) | func (f *File) drawChartSeriesDPt(i int, opts *Chart) []*cDPt {
  method drawChartSeriesCat (line 928) | func (f *File) drawChartSeriesCat(v ChartSeries, opts *Chart) *cCat {
  method drawChartSeriesVal (line 943) | func (f *File) drawChartSeriesVal(v ChartSeries, opts *Chart) *cVal {
  method drawChartSeriesMarker (line 959) | func (f *File) drawChartSeriesMarker(i int, opts *Chart) *cMarker {
  method drawChartSeriesXVal (line 995) | func (f *File) drawChartSeriesXVal(v ChartSeries, opts *Chart) *cCat {
  method drawChartSeriesYVal (line 1007) | func (f *File) drawChartSeriesYVal(v ChartSeries, opts *Chart) *cVal {
  method drawCharSeriesBubbleSize (line 1020) | func (f *File) drawCharSeriesBubbleSize(v ChartSeries, opts *Chart) *cVal {
  method drawCharSeriesBubble3D (line 1038) | func (f *File) drawCharSeriesBubble3D(opts *Chart) *attrValBool {
  method drawChartNumFmt (line 1047) | func (f *File) drawChartNumFmt(labels ChartNumFmt) *cNumFmt {
  method drawChartDLbls (line 1060) | func (f *File) drawChartDLbls(opts *Chart) *cDLbls {
  function inSupportedChartDataLabelsPositionType (line 1076) | func inSupportedChartDataLabelsPositionType(a []ChartDataLabelPositionTy...
  method drawChartSeriesDLbls (line 1087) | func (f *File) drawChartSeriesDLbls(i int, opts *Chart) *cDLbls {
  method drawPlotAreaCatAx (line 1108) | func (f *File) drawPlotAreaCatAx(pa *cPlotArea, opts *Chart) []*cAxs {
  method drawPlotAreaValAx (line 1163) | func (f *File) drawPlotAreaValAx(pa *cPlotArea, opts *Chart) []*cAxs {
  method drawPlotAreaSerAx (line 1225) | func (f *File) drawPlotAreaSerAx(opts *Chart) []*cAxs {
  function drawChartFont (line 1253) | func drawChartFont(fnt *Font, r *aRPr) {
  method drawPlotAreaTitles (line 1292) | func (f *File) drawPlotAreaTitles(runs []RichTextRun, vert string) *cTit...
  method drawPlotAreaDTable (line 1313) | func (f *File) drawPlotAreaDTable(opts *Chart) *cDTable {
  method drawPlotAreaSpPr (line 1326) | func (f *File) drawPlotAreaSpPr() *cSpPr {
  method drawPlotAreaTxPr (line 1345) | func (f *File) drawPlotAreaTxPr(opts *ChartAxis) *cTxPr {
  method drawChartLn (line 1394) | func (f *File) drawChartLn(opts *ChartLine) *aLn {
  method drawChartLegend (line 1429) | func (c *cChart) drawChartLegend(opts *Chart) {
  method drawingParser (line 1462) | func (f *File) drawingParser(path string) (*xlsxWsDr, int, error) {
  method addDrawingChart (line 1513) | func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, he...
  method addSheetDrawingChart (line 1576) | func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *Gr...
  method deleteDrawing (line 1619) | func (f *File) deleteDrawing(col, row int, drawingXML, drawingType strin...
  function extractEmbedRID (line 1682) | func extractEmbedRID(pic *xlsxPic, decodePic *decodePic) string {
  function getUnusedCellAnchorRID (line 1695) | func getUnusedCellAnchorRID(delRID, refRID []string, rIDMaps map[string]...
  method deleteDrawingRels (line 1707) | func (f *File) deleteDrawingRels(rels, rID string) {
  method genAxID (line 1724) | func (f *File) genAxID(opts *Chart) []*attrValInt {

FILE: drawing_test.go
  function TestDrawingParser (line 22) | func TestDrawingParser(t *testing.T) {
  function TestDeleteDrawingRels (line 42) | func TestDeleteDrawingRels(t *testing.T) {

FILE: errors.go
  type ErrSheetNotExist (line 201) | type ErrSheetNotExist struct
    method Error (line 206) | func (err ErrSheetNotExist) Error() string {
  function newAddCommentError (line 212) | func newAddCommentError(cell string) error {
  function newCellNameToCoordinatesError (line 218) | func newCellNameToCoordinatesError(cell string, err error) error {
  function newCoordinatesToCellNameError (line 224) | func newCoordinatesToCellNameError(col, row int) error {
  function newFieldLengthError (line 230) | func newFieldLengthError(name string) error {
  function newInvalidAutoFilterColumnError (line 236) | func newInvalidAutoFilterColumnError(col string) error {
  function newInvalidAutoFilterExpError (line 242) | func newInvalidAutoFilterExpError(exp string) error {
  function newInvalidAutoFilterOperatorError (line 248) | func newInvalidAutoFilterOperatorError(op, exp string) error {
  function newInvalidCellNameError (line 254) | func newInvalidCellNameError(cell string) error {
  function newInvalidColumnNameError (line 260) | func newInvalidColumnNameError(col string) error {
  function newInvalidExcelDateError (line 266) | func newInvalidExcelDateError(dateValue float64) error {
  function newInvalidLinkTypeError (line 272) | func newInvalidLinkTypeError(linkType string) error {
  function newInvalidNameError (line 278) | func newInvalidNameError(name string) error {
  function newInvalidOptionalValue (line 284) | func newInvalidOptionalValue(name, value string, values []string) error {
  function newInvalidRowNumberError (line 290) | func newInvalidRowNumberError(row int) error {
  function newInvalidSlicerNameError (line 296) | func newInvalidSlicerNameError(name string) error {
  function newInvalidStyleID (line 302) | func newInvalidStyleID(styleID int) error {
  function newNoExistSlicerError (line 308) | func newNoExistSlicerError(name string) error {
  function newNoExistTableError (line 314) | func newNoExistTableError(name string) error {
  function newNotWorksheetError (line 320) | func newNotWorksheetError(name string) error {
  function newPivotTableColFieldsError (line 326) | func newPivotTableColFieldsError(data []string) error {
  function newPivotTableRowFieldsError (line 332) | func newPivotTableRowFieldsError(data []string) error {
  function newPivotTableDataRangeError (line 338) | func newPivotTableDataRangeError(msg string) error {
  function newPivotTableRangeError (line 344) | func newPivotTableRangeError(msg string) error {
  function newStreamSetRowError (line 350) | func newStreamSetRowError(row int) error {
  function newStreamSetRowOrderError (line 356) | func newStreamSetRowOrderError(name string) error {
  function newUnknownFilterTokenError (line 362) | func newUnknownFilterTokenError(token string) error {
  function newUnsupportedChartType (line 368) | func newUnsupportedChartType(chartType ChartType) error {
  function newUnsupportedPivotCacheSourceType (line 374) | func newUnsupportedPivotCacheSourceType(sourceType string) error {
  function newUnzipSizeLimitError (line 380) | func newUnzipSizeLimitError(unzipSizeLimit int64) error {
  function newViewIdxError (line 386) | func newViewIdxError(viewIndex int) error {

FILE: errors_test.go
  function TestNewInvalidColNameError (line 9) | func TestNewInvalidColNameError(t *testing.T) {
  function TestNewInvalidRowNumberError (line 14) | func TestNewInvalidRowNumberError(t *testing.T) {
  function TestNewInvalidCellNameError (line 18) | func TestNewInvalidCellNameError(t *testing.T) {
  function TestNewInvalidExcelDateError (line 23) | func TestNewInvalidExcelDateError(t *testing.T) {

FILE: excelize.go
  type File (line 31) | type File struct
    method checkOpenReaderOptions (line 171) | func (f *File) checkOpenReaderOptions() error {
    method getOptions (line 237) | func (f *File) getOptions(opts ...Options) *Options {
    method CharsetTranscoder (line 247) | func (f *File) CharsetTranscoder(fn func(charset string, input io.Read...
    method SetZipWriter (line 253) | func (f *File) SetZipWriter(fn func(io.Writer) ZipWriter) *File { f.Zi...
    method xmlNewDecoder (line 256) | func (f *File) xmlNewDecoder(rdr io.Reader) (ret *xml.Decoder) {
    method setDefaultTimeStyle (line 265) | func (f *File) setDefaultTimeStyle(sheet, cell string, format int) err...
    method workSheetReader (line 282) | func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err e...
    method setRels (line 418) | func (f *File) setRels(rID, relPath, relType, target, targetMode strin...
    method addRels (line 440) | func (f *File) addRels(relPath, relType, target, targetMode string) int {
    method UpdateLinkedValue (line 502) | func (f *File) UpdateLinkedValue() error {
    method AddVBAProject (line 553) | func (f *File) AddVBAProject(file []byte) error {
    method setContentTypePartProjectExtensions (line 591) | func (f *File) setContentTypePartProjectExtensions(contentType string)...
    method metadataReader (line 620) | func (f *File) metadataReader() (*xlsxMetadata, error) {
    method richValueReader (line 631) | func (f *File) richValueReader() (*xlsxRichValueData, error) {
    method richValueRelReader (line 642) | func (f *File) richValueRelReader() (*xlsxRichValueRels, error) {
    method richValueStructuresReader (line 653) | func (f *File) richValueStructuresReader() (*xlsxRichValueStructures, ...
    method richValueWebImageReader (line 664) | func (f *File) richValueWebImageReader() (*xlsxWebImagesSupportingRich...
    method getRichDataRichValueRelRelationships (line 675) | func (f *File) getRichDataRichValueRelRelationships(rID string) *xlsxR...
    method getRichValueWebImageRelationships (line 690) | func (f *File) getRichValueWebImageRelationships(rID string) *xlsxRela...
  type ZipWriter (line 70) | type ZipWriter interface
  type Options (line 113) | type Options struct
  function OpenFile (line 133) | func OpenFile(filename string, opts ...Options) (*File, error) {
  function newFile (line 150) | func newFile() *File {
  function OpenReader (line 192) | func OpenReader(r io.Reader, opts ...Options) (*File, error) {
  method checkSheet (line 331) | func (ws *xlsxWorksheet) checkSheet() {
  method checkSheetR0 (line 388) | func (ws *xlsxWorksheet) checkSheetR0(sheetData *xlsxSheetData, rowData ...

FILE: excelize_test.go
  function TestOpenFile (line 27) | func TestOpenFile(t *testing.T) {
  function TestSaveFile (line 200) | func TestSaveFile(t *testing.T) {
  function TestSaveAsWrongPath (line 239) | func TestSaveAsWrongPath(t *testing.T) {
  function TestCharsetTranscoder (line 247) | func TestCharsetTranscoder(t *testing.T) {
  function TestOpenReader (line 252) | func TestOpenReader(t *testing.T) {
  function TestBrokenFile (line 362) | func TestBrokenFile(t *testing.T) {
  function TestNewFile (line 393) | func TestNewFile(t *testing.T) {
  function TestSetCellHyperLink (line 417) | func TestSetCellHyperLink(t *testing.T) {
  function TestGetCellHyperLink (line 506) | func TestGetCellHyperLink(t *testing.T) {
  function TestSetSheetBackground (line 556) | func TestSetSheetBackground(t *testing.T) {
  function TestSetSheetBackgroundErrors (line 565) | func TestSetSheetBackgroundErrors(t *testing.T) {
  function TestWriteArrayFormula (line 593) | func TestWriteArrayFormula(t *testing.T) {
  function TestSetCellStyleAlignment (line 695) | func TestSetCellStyleAlignment(t *testing.T) {
  function TestSetCellStyleBorder (line 722) | func TestSetCellStyleBorder(t *testing.T) {
  function TestSetCellStyleBorderErrors (line 797) | func TestSetCellStyleBorderErrors(t *testing.T) {
  function TestSetCellStyleNumberFormat (line 806) | func TestSetCellStyleNumberFormat(t *testing.T) {
  function TestSetCellStyleCurrencyNumberFormat (line 860) | func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
  function TestSetCellStyleLangNumberFormat (line 906) | func TestSetCellStyleLangNumberFormat(t *testing.T) {
  function TestSetCellStyleCustomNumberFormat (line 950) | func TestSetCellStyleCustomNumberFormat(t *testing.T) {
  function TestSetCellStyleFill (line 968) | func TestSetCellStyleFill(t *testing.T) {
  function TestSetCellStyleFont (line 985) | func TestSetCellStyleFont(t *testing.T) {
  function TestSetCellStyleProtection (line 1018) | func TestSetCellStyleProtection(t *testing.T) {
  function TestSetDeleteSheet (line 1031) | func TestSetDeleteSheet(t *testing.T) {
  function TestSheetVisibility (line 1049) | func TestSheetVisibility(t *testing.T) {
  function TestCopySheet (line 1063) | func TestCopySheet(t *testing.T) {
  function TestCopySheetError (line 1079) | func TestCopySheetError(t *testing.T) {
  function TestGetSheetComments (line 1087) | func TestGetSheetComments(t *testing.T) {
  function TestGetActiveSheetIndex (line 1092) | func TestGetActiveSheetIndex(t *testing.T) {
  function TestRelsWriter (line 1098) | func TestRelsWriter(t *testing.T) {
  function TestConditionalFormat (line 1104) | func TestConditionalFormat(t *testing.T) {
  function TestSharedStrings (line 1324) | func TestSharedStrings(t *testing.T) {
  function TestSetSheetCol (line 1336) | func TestSetSheetCol(t *testing.T) {
  function TestSetSheetRow (line 1352) | func TestSetSheetRow(t *testing.T) {
  function TestHSL (line 1368) | func TestHSL(t *testing.T) {
  function TestProtectSheet (line 1412) | func TestProtectSheet(t *testing.T) {
  function TestUnprotectSheet (line 1466) | func TestUnprotectSheet(t *testing.T) {
  function TestProtectWorkbook (line 1495) | func TestProtectWorkbook(t *testing.T) {
  function TestUnprotectWorkbook (line 1526) | func TestUnprotectWorkbook(t *testing.T) {
  function TestSetDefaultTimeStyle (line 1556) | func TestSetDefaultTimeStyle(t *testing.T) {
  function TestAddVBAProject (line 1565) | func TestAddVBAProject(t *testing.T) {
  function TestContentTypesReader (line 1583) | func TestContentTypesReader(t *testing.T) {
  function TestWorkbookReader (line 1592) | func TestWorkbookReader(t *testing.T) {
  function TestWorkSheetReader (line 1601) | func TestWorkSheetReader(t *testing.T) {
  function TestRelsReader (line 1619) | func TestRelsReader(t *testing.T) {
  function TestDeleteSheetFromWorkbookRels (line 1629) | func TestDeleteSheetFromWorkbookRels(t *testing.T) {
  function TestUpdateLinkedValue (line 1636) | func TestUpdateLinkedValue(t *testing.T) {
  function TestAttrValToInt (line 1644) | func TestAttrValToInt(t *testing.T) {
  function prepareTestBook1 (line 1651) | func prepareTestBook1() (*File, error) {
  function prepareTestBook3 (line 1688) | func prepareTestBook3() (*File, error) {
  function prepareTestBook4 (line 1713) | func prepareTestBook4() (*File, error) {
  function prepareTestBook5 (line 1731) | func prepareTestBook5(opts Options) (*File, error) {
  function fillCells (line 1756) | func fillCells(f *File, sheet string, colCount, rowCount int) error {
  function BenchmarkOpenFile (line 1768) | func BenchmarkOpenFile(b *testing.B) {

FILE: file.go
  function NewFile (line 31) | func NewFile(opts ...Options) *File {
  method Save (line 59) | func (f *File) Save(opts ...Options) error {
  method SaveAs (line 71) | func (f *File) SaveAs(name string, opts ...Options) error {
  method Close (line 90) | func (f *File) Close() error {
  method Write (line 111) | func (f *File) Write(w io.Writer, opts ...Options) error {
  method WriteTo (line 117) | func (f *File) WriteTo(w io.Writer, opts ...Options) (int64, error) {
  method WriteToBuffer (line 139) | func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
  method writeToZip (line 163) | func (f *File) writeToZip(zw ZipWriter) error {
  method writeZip64LFH (line 250) | func (f *File) writeZip64LFH(buf *bytes.Buffer) error {

FILE: file_test.go
  type errZipWriter (line 25) | type errZipWriter struct
    method Create (line 30) | func (m *errZipWriter) Create(name string) (io.Writer, error) {
    method AddFS (line 37) | func (m *errZipWriter) AddFS(fs.FS) error { return nil }
    method Close (line 39) | func (m *errZipWriter) Close() error { return m.closeErr }
  type errWriter (line 41) | type errWriter struct
    method Write (line 43) | func (e *errWriter) Write([]byte) (int, error) { return 0, e.err }
  function BenchmarkWrite (line 45) | func BenchmarkWrite(b *testing.B) {
  function TestWriteTo (line 67) | func TestWriteTo(t *testing.T) {
  function TestClose (line 184) | func TestClose(t *testing.T) {
  function TestZip64 (line 190) | func TestZip64(t *testing.T) {
  function TestRemoveTempFiles (line 257) | func TestRemoveTempFiles(t *testing.T) {

FILE: hsl.go
  type HSL (line 42) | type HSL struct
    method RGBA (line 48) | func (c HSL) RGBA() (uint32, uint32, uint32, uint32) {
  function hslModel (line 54) | func hslModel(c color.Color) color.Color {
  function RGBToHSL (line 64) | func RGBToHSL(r, g, b uint8) (h, s, l float64) {
  function HSLToRGB (line 99) | func HSLToRGB(h, s, l float64) (r, g, b uint8) {
  function hueToRGB (line 122) | func hueToRGB(p, q, t float64) float64 {

FILE: lib.go
  method ReadZipReader (line 33) | func (f *File) ReadZipReader(r *zip.Reader) (map[string][]byte, int, err...
  method unzipToTemp (line 84) | func (f *File) unzipToTemp(zipFile *zip.File) (string, error) {
  method readXML (line 103) | func (f *File) readXML(name string) []byte {
  method readBytes (line 114) | func (f *File) readBytes(name string) []byte {
  method readTemp (line 130) | func (f *File) readTemp(name string) (file *os.File, err error) {
  method saveFileList (line 141) | func (f *File) saveFileList(name string, content []byte) {
  function readFile (line 146) | func readFile(file *zip.File) ([]byte, error) {
  function SplitCellName (line 162) | func SplitCellName(cell string) (string, int, error) {
  function JoinCellName (line 179) | func JoinCellName(col string, row int) (string, error) {
  function ColumnNameToNumber (line 205) | func ColumnNameToNumber(name string) (int, error) {
  function ColumnNumberToName (line 234) | func ColumnNumberToName(num int) (string, error) {
  function CellNameToCoordinates (line 259) | func CellNameToCoordinates(cell string) (int, int, error) {
  function CoordinatesToCellName (line 278) | func CoordinatesToCellName(col, row int, abs ...bool) (string, error) {
  function rangeRefToCoordinates (line 297) | func rangeRefToCoordinates(ref string) ([]int, error) {
  function cellRefsToCoordinates (line 307) | func cellRefsToCoordinates(firstCell, lastCell string) ([]int, error) {
  function sortCoordinates (line 320) | func sortCoordinates(coordinates []int) error {
  function coordinatesToRangeRef (line 335) | func coordinatesToRangeRef(coordinates []int, abs ...bool) (string, erro...
  method getDefinedNameRefTo (line 351) | func (f *File) getDefinedNameRefTo(definedNameName, currentSheet string)...
  function flatSqref (line 372) | func flatSqref(sqref string) (cells map[int][][]int, err error) {
  function inCoordinates (line 409) | func inCoordinates(a [][]int, x []int) int {
  function inStrSlice (line 420) | func inStrSlice(a []string, x string, caseSensitive bool) int {
  function inFloat64Slice (line 434) | func inFloat64Slice(a []float64, x float64) int {
  function boolPtr (line 444) | func boolPtr(b bool) *bool { return &b }
  function intPtr (line 447) | func intPtr(i int) *int { return &i }
  function uintPtr (line 450) | func uintPtr(u uint) *uint { return &u }
  function float64Ptr (line 453) | func float64Ptr(f float64) *float64 { return &f }
  function stringPtr (line 456) | func stringPtr(s string) *string { return &s }
  method Value (line 459) | func (attr *attrValFloat) Value() float64 {
  method Value (line 467) | func (avb *attrValBool) Value() bool {
  method Value (line 475) | func (avb *attrValString) Value() string {
  method MarshalXML (line 484) | func (avb attrValBool) MarshalXML(e *xml.Encoder, start xml.StartElement...
  method UnmarshalXML (line 508) | func (avb *attrValBool) UnmarshalXML(d *xml.Decoder, start xml.StartElem...
  method MarshalXML (line 547) | func (ext xlsxExt) MarshalXML(e *xml.Encoder, start xml.StartElement) er...
  method UnmarshalXML (line 554) | func (ext *xlsxExt) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
  function namespaceStrictToTransitional (line 575) | func namespaceStrictToTransitional(content []byte) []byte {
  function bytesReplace (line 595) | func bytesReplace(s, source, target []byte, n int) []byte {
  function genSheetPasswd (line 637) | func genSheetPasswd(plaintext string) string {
  function getRootElement (line 653) | func getRootElement(d *xml.Decoder) []xml.Attr {
  function genXMLNamespace (line 683) | func genXMLNamespace(attr []xml.Attr) string {
  function getXMLNamespace (line 699) | func getXMLNamespace(space string, attr []xml.Attr) string {
  method replaceNameSpaceBytes (line 710) | func (f *File) replaceNameSpaceBytes(path string, contentMarshal []byte)...
  method addNameSpaces (line 721) | func (f *File) addNameSpaces(path string, ns xml.Attr) {
  method setIgnorableNameSpace (line 763) | func (f *File) setIgnorableNameSpace(path string, index int, ns xml.Attr) {
  method addSheetNameSpace (line 773) | func (f *File) addSheetNameSpace(sheet string, ns xml.Attr) {
  function isNumeric (line 780) | func isNumeric(s string) (bool, int, float64) {
  function bstrUnmarshal (line 811) | func bstrUnmarshal(s string) (result string) {
  function bstrMarshal (line 835) | func bstrMarshal(s string) (result string) {
  function floatToFraction (line 868) | func floatToFraction(x float64, numeratorPlaceHolder, denominatorPlaceHo...
  function floatToFracUseContinuedFraction (line 885) | func floatToFracUseContinuedFraction(r float64, denominatorLimit int64) ...
  function assignFieldValue (line 917) | func assignFieldValue(field string, immutable, mutable reflect.Value) {
  function setPtrFields (line 931) | func setPtrFields(immutable, mutable reflect.Value) {
  function setNoPtrFieldsVal (line 943) | func setNoPtrFieldsVal(fields []string, immutable, mutable reflect.Value) {
  function setPtrFieldsVal (line 958) | func setPtrFieldsVal(fields []string, immutable, mutable reflect.Value) {
  function countUTF16String (line 977) | func countUTF16String(s string) int {
  function truncateUTF16Units (line 987) | func truncateUTF16Units(s string, length int) string {
  type Stack (line 998) | type Stack struct
    method Push (line 1009) | func (stack *Stack) Push(value interface{}) {
    method Pop (line 1014) | func (stack *Stack) Pop() interface{} {
    method Peek (line 1024) | func (stack *Stack) Peek() interface{} {
    method Len (line 1033) | func (stack *Stack) Len() int {
    method Empty (line 1038) | func (stack *Stack) Empty() bool {
  function NewStack (line 1003) | func NewStack() *Stack {

FILE: lib_test.go
  function TestColumnNameToNumber_OK (line 64) | func TestColumnNameToNumber_OK(t *testing.T) {
  function TestColumnNameToNumber_Error (line 74) | func TestColumnNameToNumber_Error(t *testing.T) {
  function TestColumnNumberToName_OK (line 86) | func TestColumnNumberToName_OK(t *testing.T) {
  function TestColumnNumberToName_Error (line 96) | func TestColumnNumberToName_Error(t *testing.T) {
  function TestSplitCellName_OK (line 111) | func TestSplitCellName_OK(t *testing.T) {
  function TestSplitCellName_Error (line 123) | func TestSplitCellName_Error(t *testing.T) {
  function TestJoinCellName_OK (line 134) | func TestJoinCellName_OK(t *testing.T) {
  function TestJoinCellName_Error (line 146) | func TestJoinCellName_Error(t *testing.T) {
  function TestCellNameToCoordinates_OK (line 165) | func TestCellNameToCoordinates_OK(t *testing.T) {
  function TestCellNameToCoordinates_Error (line 177) | func TestCellNameToCoordinates_Error(t *testing.T) {
  function TestCoordinatesToCellName_OK (line 190) | func TestCoordinatesToCellName_OK(t *testing.T) {
  function TestCoordinatesToCellName_Error (line 201) | func TestCoordinatesToCellName_Error(t *testing.T) {
  function TestCoordinatesToRangeRef (line 220) | func TestCoordinatesToRangeRef(t *testing.T) {
  function TestSortCoordinates (line 232) | func TestSortCoordinates(t *testing.T) {
  function TestInStrSlice (line 236) | func TestInStrSlice(t *testing.T) {
  function TestAttrValue (line 240) | func TestAttrValue(t *testing.T) {
  function TestBoolValMarshal (line 246) | func TestBoolValMarshal(t *testing.T) {
  function TestBoolValUnmarshalXML (line 262) | func TestBoolValUnmarshalXML(t *testing.T) {
  function TestExtUnmarshalXML (line 276) | func TestExtUnmarshalXML(t *testing.T) {
  function TestBytesReplace (line 285) | func TestBytesReplace(t *testing.T) {
  function TestGetRootElement (line 290) | func TestGetRootElement(t *testing.T) {
  function TestSetIgnorableNameSpace (line 298) | func TestSetIgnorableNameSpace(t *testing.T) {
  function TestStack (line 307) | func TestStack(t *testing.T) {
  function TestGenXMLNamespace (line 313) | func TestGenXMLNamespace(t *testing.T) {
  function TestBstrUnmarshal (line 319) | func TestBstrUnmarshal(t *testing.T) {
  function TestBstrMarshal (line 344) | func TestBstrMarshal(t *testing.T) {
  function TestTruncateUTF16Units (line 357) | func TestTruncateUTF16Units(t *testing.T) {
  function TestReadBytes (line 379) | func TestReadBytes(t *testing.T) {
  function TestUnzipToTemp (line 386) | func TestUnzipToTemp(t *testing.T) {
  function TestFloat2Frac (line 419) | func TestFloat2Frac(t *testing.T) {

FILE: merge.go
  method Rect (line 17) | func (mc *xlsxMergeCell) Rect() ([]int, error) {
  method MergeCell (line 52) | func (f *File) MergeCell(sheet, topLeftCell, bottomRightCell string) err...
  method UnmergeCell (line 96) | func (f *File) UnmergeCell(sheet, topLeftCell, bottomRightCell string) e...
  method GetMergeCells (line 146) | func (f *File) GetMergeCells(sheet string, withoutValues ...bool) ([]Mer...
  method mergeOverlapCells (line 176) | func (ws *xlsxWorksheet) mergeOverlapCells() error {
  type MergeCell (line 230) | type MergeCell
    method GetCellValue (line 233) | func (m *MergeCell) GetCellValue() string {
    method GetStartAxis (line 239) | func (m *MergeCell) GetStartAxis() string {
    method GetEndAxis (line 245) | func (m *MergeCell) GetEndAxis() string {

FILE: merge_test.go
  function TestMergeCell (line 10) | func TestMergeCell(t *testing.T) {
  function TestMergeCellOverlap (line 92) | func TestMergeCellOverlap(t *testing.T) {
  function TestGetMergeCells (line 111) | func TestGetMergeCells(t *testing.T) {
  function TestUnmergeCell (line 168) | func TestUnmergeCell(t *testing.T) {
  function TestMergeCellsParser (line 220) | func TestMergeCellsParser(t *testing.T) {

FILE: numfmt.go
  type languageInfo (line 27) | type languageInfo struct
  type numberFormat (line 36) | type numberFormat struct
    method prepareNumberic (line 5251) | func (nf *numberFormat) prepareNumberic(value string) {
    method getNumberPartLen (line 5288) | func (nf *numberFormat) getNumberPartLen() (int, int) {
    method getNumberFmtConf (line 5312) | func (nf *numberFormat) getNumberFmtConf() {
    method printNumberLiteral (line 5376) | func (nf *numberFormat) printNumberLiteral(text string) string {
    method fractionHandler (line 5440) | func (nf *numberFormat) fractionHandler(frac float64, token nfp.Token,...
    method printSwitchArgument (line 5474) | func (nf *numberFormat) printSwitchArgument(text string) string {
    method printBigNumber (line 5486) | func (nf *numberFormat) printBigNumber(decimal float64, fracLen int) s...
    method numberHandler (line 5516) | func (nf *numberFormat) numberHandler() string {
    method dateTimeHandler (line 5558) | func (nf *numberFormat) dateTimeHandler() string {
    method alignmentHandler (line 5599) | func (nf *numberFormat) alignmentHandler(result string) string {
    method positiveHandler (line 5615) | func (nf *numberFormat) positiveHandler() string {
    method currencyLanguageHandler (line 5655) | func (nf *numberFormat) currencyLanguageHandler(token nfp.Token) (bool...
    method localAmPm (line 5689) | func (nf *numberFormat) localAmPm(ap string) string {
    method localMonthsName (line 7443) | func (nf *numberFormat) localMonthsName(abbr int) string {
    method dateAmPmHandler (line 7458) | func (nf *numberFormat) dateAmPmHandler(i int, token nfp.Token) {
    method dateTimesHandler (line 7472) | func (nf *numberFormat) dateTimesHandler(i int, token nfp.Token) {
    method japaneseYearHandler (line 7527) | func (nf *numberFormat) japaneseYearHandler(token nfp.Token, langInfo ...
    method republicOfChinaYearHandler (line 7565) | func (nf *numberFormat) republicOfChinaYearHandler(token nfp.Token, la...
    method yearsHandler (line 7601) | func (nf *numberFormat) yearsHandler(token nfp.Token) {
    method daysHandler (line 7636) | func (nf *numberFormat) daysHandler(token nfp.Token) {
    method hoursHandler (line 7681) | func (nf *numberFormat) hoursHandler(i int, token nfp.Token) {
    method minutesHandler (line 7715) | func (nf *numberFormat) minutesHandler(token nfp.Token) {
    method secondsHandler (line 7730) | func (nf *numberFormat) secondsHandler(token nfp.Token) {
    method elapsedDateTimesHandler (line 7743) | func (nf *numberFormat) elapsedDateTimesHandler(token nfp.Token) {
    method hoursNext (line 7759) | func (nf *numberFormat) hoursNext(i int) int {
    method apNext (line 7773) | func (nf *numberFormat) apNext(i int) ([]string, bool) {
    method isMonthToken (line 7791) | func (nf *numberFormat) isMonthToken(i int) bool {
    method negativeHandler (line 7815) | func (nf *numberFormat) negativeHandler() (result string) {
    method textHandler (line 7828) | func (nf *numberFormat) textHandler() (result string) {
    method getValueSectionType (line 7842) | func (nf *numberFormat) getValueSectionType(value string) (float64, st...
  type CultureName (line 53) | type CultureName
  constant CultureNameUnknown (line 58) | CultureNameUnknown CultureName = iota
  constant CultureNameEnUS (line 59) | CultureNameEnUS
  constant CultureNameJaJP (line 60) | CultureNameJaJP
  constant CultureNameKoKR (line 61) | CultureNameKoKR
  constant CultureNameZhCN (line 62) | CultureNameZhCN
  constant CultureNameZhTW (line 63) | CultureNameZhTW
  function getSupportedLanguageInfo (line 5057) | func getSupportedLanguageInfo(lang string) (languageInfo, bool) {
  method applyBuiltInNumFmt (line 5080) | func (f *File) applyBuiltInNumFmt(c *xlsxC, fmtCode string, numFmtID int...
  method langNumFmtFuncEnUS (line 5094) | func (f *File) langNumFmtFuncEnUS(numFmtID int) string {
  method langNumFmtFuncJaJP (line 5113) | func (f *File) langNumFmtFuncJaJP(numFmtID int) string {
  method langNumFmtFuncKoKR (line 5125) | func (f *File) langNumFmtFuncKoKR(numFmtID int) string {
  method langNumFmtFuncZhCN (line 5137) | func (f *File) langNumFmtFuncZhCN(numFmtID int) string {
  method langNumFmtFuncZhTW (line 5149) | func (f *File) langNumFmtFuncZhTW(numFmtID int) string {
  method checkDateTimePattern (line 5160) | func (f *File) checkDateTimePattern() error {
  function extractNumFmtDecimal (line 5176) | func extractNumFmtDecimal(tokens []nfp.Token) (int, bool, bool) {
  method extractNumFmtDecimal (line 5196) | func (f *File) extractNumFmtDecimal(fmtCode string) int {
  method getBuiltInNumFmtCode (line 5237) | func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) {
  function format (line 5263) | func format(value, numFmt string, date1904 bool, cellType CellType, opts...
  function handleDigitsLiteral (line 5355) | func handleDigitsLiteral(text string, tokenValueLen, intPartLen, hashZer...
  function printCommaSep (line 5454) | func printCommaSep(text string) string {
  function localMonthsNameAfrikaans (line 5697) | func localMonthsNameAfrikaans(t time.Time, abbr int) string {
  function localMonthsNameAlbanian (line 5708) | func localMonthsNameAlbanian(t time.Time, abbr int) string {
  function localMonthsNameAlsatian (line 5719) | func localMonthsNameAlsatian(t time.Time, abbr int) string {
  function localMonthsNameAlsatianFrance (line 5730) | func localMonthsNameAlsatianFrance(t time.Time, abbr int) string {
  function localMonthsNameAmharic (line 5741) | func localMonthsNameAmharic(t time.Time, abbr int) string {
  function localMonthsNameArabic (line 5752) | func localMonthsNameArabic(t time.Time, abbr int) string {
  function localMonthsNameArabicIraq (line 5760) | func localMonthsNameArabicIraq(t time.Time, abbr int) string {
  function localMonthsNameArmenian (line 5768) | func localMonthsNameArmenian(t time.Time, abbr int) string {
  function localMonthsNameAssamese (line 5779) | func localMonthsNameAssamese(t time.Time, abbr int) string {
  function localMonthsNameAzerbaijaniCyrillic (line 5790) | func localMonthsNameAzerbaijaniCyrillic(t time.Time, abbr int) string {
  function localMonthsNameAzerbaijani (line 5801) | func localMonthsNameAzerbaijani(t time.Time, abbr int) string {
  function localMonthsNameAustria (line 5812) | func localMonthsNameAustria(t time.Time, abbr int) string {
  function localMonthsNameBangla (line 5823) | func localMonthsNameBangla(t time.Time, abbr int) string {
  function localMonthsNameBashkir (line 5831) | func localMonthsNameBashkir(t time.Time, abbr int) string {
  function localMonthsNameBasque (line 5842) | func localMonthsNameBasque(t time.Time, abbr int) string {
  function localMonthsNameBelarusian (line 5853) | func localMonthsNameBelarusian(t time.Time, abbr int) string {
  function localMonthsNameBosnianCyrillic (line 5864) | func localMonthsNameBosnianCyrillic(t time.Time, abbr int) string {
  function localMonthsNameBosnian (line 5875) | func localMonthsNameBosnian(t time.Time, abbr int) string {
  function localMonthsNameBreton (line 5886) | func localMonthsNameBreton(t time.Time, abbr int) string {
  function localMonthsNameBulgarian (line 5897) | func localMonthsNameBulgarian(t time.Time, abbr int) string {
  function localMonthsNameBurmese (line 5908) | func localMonthsNameBurmese(t time.Time, abbr int) string {
  function localMonthsNameCaribbean (line 5919) | func localMonthsNameCaribbean(t time.Time, abbr int) string {
  function localMonthsNameCentralKurdish (line 5930) | func localMonthsNameCentralKurdish(t time.Time, abbr int) string {
  function localMonthsNameCherokee (line 5938) | func localMonthsNameCherokee(t time.Time, abbr int) string {
  function localMonthsNameChinese1 (line 5949) | func localMonthsNameChinese1(t time.Time, abbr int) string {
  function localMonthsNameChinese2 (line 5960) | func localMonthsNameChinese2(t time.Time, abbr int) string {
  function localMonthsNameChinese3 (line 5968) | func localMonthsNameChinese3(t time.Time, abbr int) string {
  function localMonthsNameCorsican (line 5976) | func localMonthsNameCorsican(t time.Time, abbr int) string {
  function localMonthsNameCroatian (line 5987) | func localMonthsNameCroatian(t time.Time, abbr int) string {
  function localMonthsNameCroatianLatin (line 5998) | func localMonthsNameCroatianLatin(t time.Time, abbr int) string {
  function localMonthsNameCzech (line 6012) | func localMonthsNameCzech(t time.Time, abbr int) string {
  function localMonthsNameDanish (line 6023) | func localMonthsNameDanish(t time.Time, abbr int) string {
  function localMonthsNameDari (line 6034) | func localMonthsNameDari(t time.Time, abbr int) string {
  function localMonthsNameDariAfghanistan (line 6046) | func localMonthsNameDariAfghanistan(t time.Time, abbr int) string {
  function localMonthsNameDivehi (line 6057) | func localMonthsNameDivehi(t time.Time, abbr int) string {
  function localMonthsNameDutch (line 6065) | func localMonthsNameDutch(t time.Time, abbr int) string {
  function localMonthsNameDzongkha (line 6076) | func localMonthsNameDzongkha(t time.Time, abbr int) string {
  function localMonthsNameEnglish (line 6087) | func localMonthsNameEnglish(t time.Time, abbr int) string {
  function localMonthsNameEstonian (line 6098) | func localMonthsNameEstonian(t time.Time, abbr int) string {
  function localMonthsNameFaroese (line 6109) | func localMonthsNameFaroese(t time.Time, abbr int) string {
  function localMonthsNameFilipino (line 6120) | func localMonthsNameFilipino(t time.Time, abbr int) string {
  function localMonthsNameFinnish (line 6131) | func localMonthsNameFinnish(t time.Time, abbr int) string {
  function localMonthsNameFrench (line 6142) | func localMonthsNameFrench(t time.Time, abbr int) string {
  function localMonthsNameFrisian (line 6157) | func localMonthsNameFrisian(t time.Time, abbr int) string {
  function localMonthsNameFulah (line 6168) | func localMonthsNameFulah(t time.Time, abbr int) string {
  function localMonthsNameGalician (line 6179) | func localMonthsNameGalician(t time.Time, abbr int) string {
  function localMonthsNameGeorgian (line 6190) | func localMonthsNameGeorgian(t time.Time, abbr int) string {
  function localMonthsNameGerman (line 6201) | func localMonthsNameGerman(t time.Time, abbr int) string {
  function localMonthsNameGreek (line 6212) | func localMonthsNameGreek(t time.Time, abbr int) string {
  function localMonthsNameGreenlandic (line 6223) | func localMonthsNameGreenlandic(t time.Time, abbr int) string {
  function localMonthsNameGuarani (line 6234) | func localMonthsNameGuarani(t time.Time, abbr int) string {
  function localMonthsNameGujarati (line 6245) | func localMonthsNameGujarati(t time.Time, abbr int) string {
  function localMonthsNameHausa (line 6256) | func localMonthsNameHausa(t time.Time, abbr int) string {
  function localMonthsNameHawaiian (line 6267) | func localMonthsNameHawaiian(t time.Time, abbr int) string {
  function localMonthsNameHebrew (line 6278) | func localMonthsNameHebrew(t time.Time, abbr int) string {
  function localMonthsNameHindi (line 6289) | func localMonthsNameHindi(t time.Time, abbr int) string {
  function localMonthsNameHungarian (line 6297) | func localMonthsNameHungarian(t time.Time, abbr int) string {
  function localMonthsNameIcelandic (line 6308) | func localMonthsNameIcelandic(t time.Time, abbr int) string {
  function localMonthsNameIgbo (line 6319) | func localMonthsNameIgbo(t time.Time, abbr int) string {
  function localMonthsNameIndonesian (line 6330) | func localMonthsNameIndonesian(t time.Time, abbr int) string {
  function localMonthsNameInuktitut (line 6341) | func localMonthsNameInuktitut(t time.Time, abbr int) string {
  function localMonthsNameIrish (line 6352) | func localMonthsNameIrish(t time.Time, abbr int) string {
  function localMonthsNameItalian (line 6363) | func localMonthsNameItalian(t time.Time, abbr int) string {
  function localMonthsNameKannada (line 6374) | func localMonthsNameKannada(t time.Time, abbr int) string {
  function localMonthsNameKashmiri (line 6385) | func localMonthsNameKashmiri(t time.Time, abbr int) string {
  function localMonthsNameKazakh (line 6393) | func localMonthsNameKazakh(t time.Time, abbr int) string {
  function localMonthsNameKhmer (line 6404) | func localMonthsNameKhmer(t time.Time, abbr int) string {
  function localMonthsNameKiche (line 6415) | func localMonthsNameKiche(t time.Time, abbr int) string {
  function localMonthsNameKinyarwanda (line 6426) | func localMonthsNameKinyarwanda(t time.Time, abbr int) string {
  function localMonthsNameKiswahili (line 6437) | func localMonthsNameKiswahili(t time.Time, abbr int) string {
  function localMonthsNameKonkani (line 6448) | func localMonthsNameKonkani(t time.Time, abbr int) string {
  function localMonthsNameKorean (line 6459) | func localMonthsNameKorean(t time.Time, abbr int) string {
  function localMonthsNameKyrgyz (line 6467) | func localMonthsNameKyrgyz(t time.Time, abbr int) string {
  function localMonthsNameLao (line 6478) | func localMonthsNameLao(t time.Time, abbr int) string {
  function localMonthsNameLatin (line 6489) | func localMonthsNameLatin(t time.Time, abbr int) string {
  function localMonthsNameLatvian (line 6500) | func localMonthsNameLatvian(t time.Time, abbr int) string {
  function localMonthsNameLithuanian (line 6511) | func localMonthsNameLithuanian(t time.Time, abbr int) string {
  function localMonthsNameLowerSorbian (line 6522) | func localMonthsNameLowerSorbian(t time.Time, abbr int) string {
  function localMonthsNameLuxembourgish (line 6533) | func localMonthsNameLuxembourgish(t time.Time, abbr int) string {
  function localMonthsNameMacedonian (line 6544) | func localMonthsNameMacedonian(t time.Time, abbr int) string {
  function localMonthsNameMalay (line 6555) | func localMonthsNameMalay(t time.Time, abbr int) string {
  function localMonthsNameMalayalam (line 6566) | func localMonthsNameMalayalam(t time.Time, abbr int) string {
  function localMonthsNameMaltese (line 6577) | func localMonthsNameMaltese(t time.Time, abbr int) string {
  function localMonthsNameMaori (line 6588) | func localMonthsNameMaori(t time.Time, abbr int) string {
  function localMonthsNameMapudungun (line 6599) | func localMonthsNameMapudungun(t time.Time, abbr int) string {
  function localMonthsNameMarathi (line 6607) | func localMonthsNameMarathi(t time.Time, abbr int) string {
  function localMonthsNameMohawk (line 6618) | func localMonthsNameMohawk(t time.Time, abbr int) string {
  function localMonthsNameMongolian (line 6629) | func localMonthsNameMongolian(t time.Time, abbr int) string {
  function localMonthsNameMorocco (line 6640) | func localMonthsNameMorocco(t time.Time, abbr int) string {
  function localMonthsNameNepali (line 6651) | func localMonthsNameNepali(t time.Time, abbr int) string {
  function localMonthsNameNepaliIN (line 6662) | func localMonthsNameNepaliIN(t time.Time, abbr int) string {
  function localMonthsNameNigeria (line 6673) | func localMonthsNameNigeria(t time.Time, abbr int) string {
  function localMonthsNameNorwegian (line 6684) | func localMonthsNameNorwegian(t time.Time, abbr int) string {
  function localMonthsNameOccitan (line 6695) | func localMonthsNameOccitan(t time.Time, abbr int) string {
  function localMonthsNameOdia (line 6706) | func localMonthsNameOdia(t time.Time, abbr int) string {
  function localMonthsNameOromo (line 6714) | func localMonthsNameOromo(t time.Time, abbr int) string {
  function localMonthsNamePashto (line 6725) | func localMonthsNamePashto(t time.Time, abbr int) string {
  function localMonthsNamePersian (line 6738) | func localMonthsNamePersian(t time.Time, abbr int) string {
  function localMonthsNamePolish (line 6746) | func localMonthsNamePolish(t time.Time, abbr int) string {
  function localMonthsNamePortuguese (line 6757) | func localMonthsNamePortuguese(t time.Time, abbr int) string {
  function localMonthsNamePunjabi (line 6768) | func localMonthsNamePunjabi(t time.Time, abbr int) string {
  function localMonthsNamePunjabiArab (line 6776) | func localMonthsNamePunjabiArab(t time.Time, abbr int) string {
  function localMonthsNameQuechua (line 6784) | func localMonthsNameQuechua(t time.Time, abbr int) string {
  function localMonthsNameQuechuaEcuador (line 6795) | func localMonthsNameQuechuaEcuador(t time.Time, abbr int) string {
  function localMonthsNameRomanian (line 6809) | func localMonthsNameRomanian(t time.Time, abbr int) string {
  function localMonthsNameRomansh (line 6820) | func localMonthsNameRomansh(t time.Time, abbr int) string {
  function localMonthsNameRussian (line 6831) | func localMonthsNameRussian(t time.Time, abbr int) string {
  function localMonthsNameSakha (line 6846) | func localMonthsNameSakha(t time.Time, abbr int) string {
  function localMonthsNameSami (line 6857) | func localMonthsNameSami(t time.Time, abbr int) string {
  function localMonthsNameSamiLule (line 6868) | func localMonthsNameSamiLule(t time.Time, abbr int) string {
  function localMonthsNameSamiNorthern (line 6879) | func localMonthsNameSamiNorthern(t time.Time, abbr int) string {
  function localMonthsNameSamiNorthernFI (line 6891) | func localMonthsNameSamiNorthernFI(t time.Time, abbr int) string {
  function localMonthsNameSamiSkolt (line 6905) | func localMonthsNameSamiSkolt(t time.Time, abbr int) string {
  function localMonthsNameSamiSouthern (line 6913) | func localMonthsNameSamiSouthern(t time.Time, abbr int) string {
  function localMonthsNameSanskrit (line 6924) | func localMonthsNameSanskrit(t time.Time, abbr int) string {
  function localMonthsNameScottishGaelic (line 6932) | func localMonthsNameScottishGaelic(t time.Time, abbr int) string {
  function localMonthsNameSerbian (line 6943) | func localMonthsNameSerbian(t time.Time, abbr int) string {
  function localMonthsNameSerbianBA (line 6955) | func localMonthsNameSerbianBA(t time.Time, abbr int) string {
  function localMonthsNameSerbianLatin (line 6966) | func localMonthsNameSerbianLatin(t time.Time, abbr int) string {
  function localMonthsNameSerbianLatinCS (line 6977) | func localMonthsNameSerbianLatinCS(t time.Time, abbr int) string {
  function localMonthsNameSesothoSaLeboa (line 6988) | func localMonthsNameSesothoSaLeboa(t time.Time, abbr int) string {
  function localMonthsNameSetswana (line 6999) | func localMonthsNameSetswana(t time.Time, abbr int) string {
  function localMonthsNameSindhi (line 7010) | func localMonthsNameSindhi(t time.Time, abbr int) string {
  function localMonthsNameSinhala (line 7018) | func localMonthsNameSinhala(t time.Time, abbr int) string {
  function localMonthsNameSlovak (line 7029) | func localMonthsNameSlovak(t time.Time, abbr int) string {
  function localMonthsNameSlovenian (line 7040) | func localMonthsNameSlovenian(t time.Time, abbr int) string {
  function localMonthsNameSomali (line 7051) | func localMonthsNameSomali(t time.Time, abbr int) string {
  function localMonthsNameSotho (line 7062) | func localMonthsNameSotho(t time.Time, abbr int) string {
  function localMonthsNameSpanish (line 7073) | func localMonthsNameSpanish(t time.Time, abbr int) string {
  function localMonthsNameSpanishPE (line 7084) | func localMonthsNameSpanishPE(t time.Time, abbr int) string {
  function localMonthsNameSwedish (line 7095) | func localMonthsNameSwedish(t time.Time, abbr int) string {
  function localMonthsNameSwedishFI (line 7106) | func localMonthsNameSwedishFI(t time.Time, abbr int) string {
  function localMonthsNameSyriac (line 7117) | func localMonthsNameSyriac(t time.Time, abbr int) string {
  function localMonthsNameTajik (line 7128) | func localMonthsNameTajik(t time.Time, abbr int) string {
  function localMonthsNameTamazight (line 7139) | func localMonthsNameTamazight(t time.Time, abbr int) string {
  function localMonthsNameTamil (line 7150) | func localMonthsNameTamil(t time.Time, abbr int) string {
  function localMonthsNameTamilLK (line 7158) | func localMonthsNameTamilLK(t time.Time, abbr int) string {
  function localMonthsNameTatar (line 7169) | func localMonthsNameTatar(t time.Time, abbr int) string {
  function localMonthsNameTelugu (line 7180) | func localMonthsNameTelugu(t time.Time, abbr int) string {
  function localMonthsNameSyllabics (line 7191) | func localMonthsNameSyllabics(t time.Time, abbr int) string {
  function localMonthsNameThai (line 7202) | func localMonthsNameThai(t time.Time, abbr int) string {
  function localMonthsNameTibetan (line 7214) | func localMonthsNameTibetan(t time.Time, abbr int) string {
  function localMonthsNameTigrinya (line 7228) | func localMonthsNameTigrinya(t time.Time, abbr int) string {
  function localMonthsNameTsonga (line 7239) | func localMonthsNameTsonga(t time.Time, abbr int) string {
  function localMonthsNameTraditionalMongolian (line 7251) | func localMonthsNameTraditionalMongolian(t time.Time, abbr int) string {
  function localMonthsNameTurkish (line 7259) | func localMonthsNameTurkish(t time.Time, abbr int) string {
  function localMonthsNameTurkmen (line 7270) | func localMonthsNameTurkmen(t time.Time, abbr int) string {
  function localMonthsNameUkrainian (line 7281) | func localMonthsNameUkrainian(t time.Time, abbr int) string {
  function localMonthsNameUpperSorbian (line 7292) | func localMonthsNameUpperSorbian(t time.Time, abbr int) string {
  function localMonthsNameUyghur (line 7303) | func localMonthsNameUyghur(t time.Time, abbr int) string {
  function localMonthsNameUzbek (line 7314) | func localMonthsNameUzbek(t time.Time, abbr int) string {
  function localMonthsNameUzbekCyrillic (line 7325) | func localMonthsNameUzbekCyrillic(t time.Time, abbr int) string {
  function localMonthsNameValencian (line 7336) | func localMonthsNameValencian(t time.Time, abbr int) string {
  function localMonthsNameVenda (line 7347) | func localMonthsNameVenda(t time.Time, abbr int) string {
  function localMonthsNameVietnamese (line 7358) | func localMonthsNameVietnamese(t time.Time, abbr int) string {
  function localMonthsNameWelsh (line 7369) | func localMonthsNameWelsh(t time.Time, abbr int) string {
  function localMonthsNameWolof (line 7380) | func localMonthsNameWolof(t time.Time, abbr int) string {
  function localMonthsNameXhosa (line 7391) | func localMonthsNameXhosa(t time.Time, abbr int) string {
  function localMonthsNameYi (line 7402) | func localMonthsNameYi(t time.Time, abbr int) string {
  function localMonthsNameYiddish (line 7410) | func localMonthsNameYiddish(t time.Time, abbr int) string {
  function localMonthsNameYoruba (line 7421) | func localMonthsNameYoruba(t time.Time, abbr int) string {
  function localMonthsNameZulu (line 7432) | func localMonthsNameZulu(t time.Time, abbr int) string {
  function eraYear (line 7515) | func eraYear(t time.Time) (int, int) {

FILE: numfmt_test.go
  function TestNumFmt (line 10) | func TestNumFmt(t *testing.T) {
  function BenchmarkNumFmtPlaceHolder (line 4336) | func BenchmarkNumFmtPlaceHolder(b *testing.B) {

FILE: picture.go
  type PictureInsertType (line 29) | type PictureInsertType
  constant PictureInsertTypePlaceOverCells (line 33) | PictureInsertTypePlaceOverCells PictureInsertType = iota
  constant PictureInsertTypePlaceInCell (line 34) | PictureInsertTypePlaceInCell
  constant PictureInsertTypeIMAGE (line 35) | PictureInsertTypeIMAGE
  constant PictureInsertTypeDISPIMG (line 36) | PictureInsertTypeDISPIMG
  method parseGraphicOptions (line 41) | func (opts *GraphicOptions) parseGraphicOptions(defaults *GraphicOptions...
  function parsePictureOptions (line 71) | func parsePictureOptions(pic *Picture) (*GraphicOptions, error) {
  method AddPicture (line 195) | func (f *File) AddPicture(sheet, cell, name string, opts *GraphicOptions...
  method AddPictureFromBytes (line 251) | func (f *File) AddPictureFromBytes(sheet, cell string, pic *Picture) err...
  method addSheetLegacyDrawing (line 314) | func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
  method addSheetLegacyDrawingHF (line 324) | func (f *File) addSheetLegacyDrawingHF(sheet string, rID int) {
  method addSheetDrawing (line 333) | func (f *File) addSheetDrawing(sheet string, rID int) {
  method addSheetPicture (line 342) | func (f *File) addSheetPicture(sheet string, rID int) error {
  method countDrawings (line 355) | func (f *File) countDrawings() int {
  method addDrawingPicture (line 375) | func (f *File) addDrawingPicture(sheet, drawingXML, cell, ext string, rI...
  method countMedia (line 477) | func (f *File) countMedia() int {
  method addMedia (line 491) | func (f *File) addMedia(file []byte, ext string) string {
  method GetPictures (line 540) | func (f *File) GetPictures(sheet, cell string) ([]Picture, error) {
  method GetPictureCells (line 574) | func (f *File) GetPictureCells(sheet string) ([]string, error) {
  method DeletePicture (line 603) | func (f *File) DeletePicture(sheet, cell string) error {
  method getPicture (line 659) | func (f *File) getPicture(row, col int, drawingXML, drawingRelationships...
  method extractPictureFromAnchor (line 689) | func (f *File) extractPictureFromAnchor(drawingRelationships string, a *...
  method calculatePictureScale (line 732) | func (f *File) calculatePictureScale(pic *Picture, cx, cy int) {
  method extractPictureFromDecodeAnchor (line 743) | func (f *File) extractPictureFromDecodeAnchor(drawingRelationships strin...
  method extractCellAnchor (line 794) | func (f *File) extractCellAnchor(anchor *xdrCellAnchor, drawingRelations...
  method extractDecodeCellAnchor (line 820) | func (f *File) extractDecodeCellAnchor(anchor *xdrCellAnchor, drawingRel...
  method getDrawingRelationships (line 842) | func (f *File) getDrawingRelationships(rels, rID string) *xlsxRelationsh...
  method drawingsWriter (line 857) | func (f *File) drawingsWriter() {
  method drawingResize (line 868) | func (f *File) drawingResize(sheet, cell string, width, height float64, ...
  method getPictureCells (line 914) | func (f *File) getPictureCells(drawingXML, drawingRelationships string) ...
  method cellImagesReader (line 959) | func (f *File) cellImagesReader() (*decodeCellImages, error) {
  method getImageCells (line 972) | func (f *File) getImageCells(sheet string) ([]string, error) {
  method getRichDataRichValueRel (line 1005) | func (f *File) getRichDataRichValueRel(val string) (*xlsxRelationship, e...
  method getRichDataWebImagesRel (line 1027) | func (f *File) getRichDataWebImagesRel(val string) (*xlsxRelationship, e...
  method getImageCellRel (line 1048) | func (f *File) getImageCellRel(c *xlsxC, pic *Picture) (*xlsxRelationshi...
  method getRichDataValueIdx (line 1098) | func (s *xlsxRichValueStructure) getRichDataValueIdx(n string) int {
  method getCellImages (line 1110) | func (f *File) getCellImages(sheet, cell string) ([]Picture, error) {
  method getDispImages (line 1133) | func (f *File) getDispImages(sheet, cell string) ([]Picture, error) {

FILE: picture_test.go
  function BenchmarkAddPictureFromBytes (line 20) | func BenchmarkAddPictureFromBytes(b *testing.B) {
  function TestAddPicture (line 34) | func TestAddPicture(t *testing.T) {
  function TestAddPictureErrors (line 187) | func TestAddPictureErrors(t *testing.T) {
  function TestGetPicture (line 220) | func TestGetPicture(t *testing.T) {
  function TestAddDrawingPicture (line 360) | func TestAddDrawingPicture(t *testing.T) {
  function TestAddPictureFromBytes (line 374) | func TestAddPictureFromBytes(t *testing.T) {
  function TestDeletePicture (line 396) | func TestDeletePicture(t *testing.T) {
  function TestDrawingResize (line 463) | func TestDrawingResize(t *testing.T) {
  function TestSetContentTypePartRelsExtensions (line 477) | func TestSetContentTypePartRelsExtensions(t *testing.T) {
  function TestSetContentTypePartImageExtensions (line 488) | func TestSetContentTypePartImageExtensions(t *testing.T) {
  function TestSetContentTypePartVMLExtensions (line 496) | func TestSetContentTypePartVMLExtensions(t *testing.T) {
  function TestAddContentTypePart (line 504) | func TestAddContentTypePart(t *testing.T) {
  function TestGetPictureCells (line 512) | func TestGetPictureCells(t *testing.T) {
  function TestExtractDecodeCellAnchor (line 538) | func TestExtractDecodeCellAnchor(t *testing.T) {
  function TestGetCellImages (line 545) | func TestGetCellImages(t *testing.T) {
  function TestGetImageCells (line 696) | func TestGetImageCells(t *testing.T) {

FILE: pivotTable.go
  type PivotTableOptions (line 35) | type PivotTableOptions struct
  type PivotTableField (line 91) | type PivotTableField struct
  method AddPivotTable (line 160) | func (f *File) AddPivotTable(opts *PivotTableOptions) error {
  method parseFormatPivotTableSet (line 197) | func (f *File) parseFormatPivotTableSet(opts *PivotTableOptions) (*xlsxW...
  method adjustRange (line 246) | func (f *File) adjustRange(rangeStr string) (string, []int, error) {
  method getTableFieldsOrder (line 277) | func (f *File) getTableFieldsOrder(opts *PivotTableOptions) ([]string, e...
  method addPivotCache (line 301) | func (f *File) addPivotCache(opts *PivotTableOptions) error {
  method addPivotTable (line 345) | func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTable...
  method addPivotRowFields (line 435) | func (f *File) addPivotRowFields(pt *xlsxPivotTableDefinition, opts *Piv...
  method addPivotPageFields (line 459) | func (f *File) addPivotPageFields(pt *xlsxPivotTableDefinition, opts *Pi...
  method addPivotDataFields (line 485) | func (f *File) addPivotDataFields(pt *xlsxPivotTableDefinition, opts *Pi...
  function inPivotTableField (line 516) | func inPivotTableField(a []PivotTableField, x string) int {
  method addPivotColFields (line 527) | func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opts *Piv...
  method setClassicLayout (line 568) | func (fld *xlsxPivotField) setClassicLayout(classicLayout bool) {
  method addPivotFields (line 576) | func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotT...
  method countPivotTables (line 668) | func (f *File) countPivotTables() int {
  method countPivotCache (line 681) | func (f *File) countPivotCache() int {
  method getPivotFieldsIndex (line 694) | func (f *File) getPivotFieldsIndex(fields []PivotTableField, opts *Pivot...
  method getPivotTableFieldsSubtotal (line 709) | func (f *File) getPivotTableFieldsSubtotal(fields []PivotTableField) []s...
  method getPivotTableFieldsName (line 728) | func (f *File) getPivotTableFieldsName(fields []PivotTableField) []string {
  method getPivotTableFieldName (line 741) | func (f *File) getPivotTableFieldName(name string, fields []PivotTableFi...
  method getPivotTableFieldsNumFmtID (line 753) | func (f *File) getPivotTableFieldsNumFmtID(fields []PivotTableField) []i...
  method getPivotTableFieldOptions (line 768) | func (f *File) getPivotTableFieldOptions(name string, fields []PivotTabl...
  method addWorkbookPivotCache (line 779) | func (f *File) addWorkbookPivotCache(RID int) int {
  method GetPivotTables (line 802) | func (f *File) GetPivotTables(sheet string) ([]PivotTableOptions, error) {
  method getPivotTableDataRange (line 832) | func (f *File) getPivotTableDataRange(opts *PivotTableOptions) error {
  method getPivotTable (line 867) | func (f *File) getPivotTable(sheet, pivotTableXML, pivotCacheRels string...
  method getPivotCacheFieldsName (line 927) | func (pc *xlsxPivotCacheDefinition) getPivotCacheFieldsName() []string {
  method pivotTableReader (line 941) | func (f *File) pivotTableReader(path string) (*xlsxPivotTableDefinition,...
  method pivotCacheReader (line 955) | func (f *File) pivotCacheReader(path string) (*xlsxPivotCacheDefinition,...
  method extractPivotTableFields (line 969) | func (f *File) extractPivotTableFields(order []string, pt *xlsxPivotTabl...
  function extractPivotTableField (line 995) | func extractPivotTableField(data string, fld *xlsxPivotField) PivotTable...
  method genPivotCacheDefinitionID (line 1007) | func (f *File) genPivotCacheDefinitionID() int {
  method deleteWorkbookPivotCache (line 1038) | func (f *File) deleteWorkbookPivotCache(opt PivotTableOptions) error {
  method DeletePivotTable (line 1063) | func (f *File) DeletePivotTable(sheet, name string) error {
  method getPivotTables (line 1106) | func (f *File) getPivotTables() (map[string][]PivotTableOptions, error) {

FILE: pivotTable_test.go
  function TestPivotTable (line 13) | func TestPivotTable(t *testing.T) {
  function TestPivotTableDataRange (line 386) | func TestPivotTableDataRange(t *testing.T) {
  function TestParseFormatPivotTableSet (line 455) | func TestParseFormatPivotTableSet(t *testing.T) {
  function TestAddPivotRowFields (line 472) | func TestAddPivotRowFields(t *testing.T) {
  function TestAddPivotPageFields (line 480) | func TestAddPivotPageFields(t *testing.T) {
  function TestAddPivotDataFields (line 488) | func TestAddPivotDataFields(t *testing.T) {
  function TestAddPivotColFields (line 496) | func TestAddPivotColFields(t *testing.T) {
  function TestGetPivotFieldsOrder (line 505) | func TestGetPivotFieldsOrder(t *testing.T) {
  function TestGetPivotTableFieldName (line 521) | func TestGetPivotTableFieldName(t *testing.T) {
  function TestGetPivotTableFieldOptions (line 526) | func TestGetPivotTableFieldOptions(t *testing.T) {
  function TestGenPivotCacheDefinitionID (line 532) | func TestGenPivotCacheDefinitionID(t *testing.T) {
  function TestDeleteWorkbookPivotCache (line 540) | func TestDeleteWorkbookPivotCache(t *testing.T) {

FILE: rows.go
  method GetRows (line 61) | func (f *File) GetRows(sheet string, opts ...Options) ([][]string, error) {
  type Rows (line 85) | type Rows struct
    method Next (line 99) | func (rows *Rows) Next() bool {
    method GetRowOpts (line 130) | func (rows *Rows) GetRowOpts() RowOpts {
    method Error (line 135) | func (rows *Rows) Error() error {
    method Close (line 141) | func (rows *Rows) Close() error {
    method Columns (line 153) | func (rows *Rows) Columns(opts ...Options) ([]string, error) {
    method rowXMLHandler (line 232) | func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElemen...
  function extractRowOpts (line 201) | func extractRowOpts(attrs []xml.Attr) RowOpts {
  function appendSpace (line 216) | func appendSpace(l int, s []string) []string {
  type rowXMLIterator (line 224) | type rowXMLIterator struct
  method cellXMLAttrHandler (line 250) | func (cell *xlsxC) cellXMLAttrHandler(start *xml.StartElement) error {
  method cellXMLHandler (line 272) | func (cell *xlsxC) cellXMLHandler(decoder *xml.Decoder, start *xml.Start...
  method Rows (line 328) | func (f *File) Rows(sheet string) (*Rows, error) {
  method getFromStringItem (line 352) | func (f *File) getFromStringItem(index int) string {
  method xmlDecoder (line 405) | func (f *File) xmlDecoder(name string) (bool, *xml.Decoder, *os.File, er...
  method SetRowHeight (line 424) | func (f *File) SetRowHeight(sheet string, row int, height float64) error {
  method getRowHeight (line 454) | func (f *File) getRowHeight(sheet string, row int) int {
  method GetRowHeight (line 480) | func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
  method sharedStringsReader (line 506) | func (f *File) sharedStringsReader() (*xlsxSST, error) {
  method SetRowVisible (line 553) | func (f *File) SetRowVisible(sheet string, row int, visible bool) error {
  method GetRowVisible (line 572) | func (f *File) GetRowVisible(sheet string, row int) (bool, error) {
  method SetRowOutlineLevel (line 592) | func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) er...
  method GetRowOutlineLevel (line 613) | func (f *File) GetRowOutlineLevel(sheet string, row int) (uint8, error) {
  method RemoveRow (line 636) | func (f *File) RemoveRow(sheet string, row int) error {
  method InsertRows (line 681) | func (f *File) InsertRows(sheet string, row, n int) error {
  method DuplicateRow (line 702) | func (f *File) DuplicateRow(sheet string, row int) error {
  method DuplicateRowTo (line 715) | func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
  function duplicateSQRefHelper (line 774) | func duplicateSQRefHelper(row, row2 int, ref string) (string, error) {
  method duplicateConditionalFormat (line 795) | func (f *File) duplicateConditionalFormat(ws *xlsxWorksheet, sheet strin...
  method duplicateDataValidations (line 823) | func (f *File) duplicateDataValidations(ws *xlsxWorksheet, sheet string,...
  method duplicateMergeCells (line 854) | func (f *File) duplicateMergeCells(ws *xlsxWorksheet, sheet string, row,...
  method checkRow (line 909) | func (ws *xlsxWorksheet) checkRow() error {
  method hasAttr (line 968) | func (r *xlsxRow) hasAttr() bool {
  method SetRowStyle (line 985) | func (f *File) SetRowStyle(sheet string, start, end, styleID int) error {
  function convertRowHeightToPixels (line 1024) | func convertRowHeightToPixels(height float64) float64 {

FILE: rows_test.go
  function TestGetRows (line 15) | func TestGetRows(t *testing.T) {
  function TestRows (line 25) | func TestRows(t *testing.T) {
  function TestRowsIterator (line 85) | func TestRowsIterator(t *testing.T) {
  function TestRowsGetRowOpts (line 116) | func TestRowsGetRowOpts(t *testing.T) {
  function TestRowsError (line 142) | func TestRowsError(t *testing.T) {
  function TestRowHeight (line 152) | func TestRowHeight(t *testing.T) {
  function TestColumns (line 218) | func TestColumns(t *testing.T) {
  function TestSharedStringsReader (line 251) | func TestSharedStringsReader(t *testing.T) {
  function TestRowVisibility (line 271) | func TestRowVisibility(t *testing.T) {
  function TestRemoveRow (line 300) | func TestRemoveRow(t *testing.T) {
  function TestInsertRows (line 366) | func TestInsertRows(t *testing.T) {
  function TestInsertRowsInEmptyFile (line 403) | func TestInsertRowsInEmptyFile(t *testing.T) {
  function prepareTestBook2 (line 417) | func prepareTestBook2() (*File, error) {
  function TestDuplicateRowFromSingleRow (line 434) | func TestDuplicateRowFromSingleRow(t *testing.T) {
  function TestDuplicateRowUpdateDuplicatedRows (line 487) | func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
  function TestDuplicateRowFirstOfMultipleRows (line 527) | func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
  function TestDuplicateRowZeroWithNoRows (line 562) | func TestDuplicateRowZeroWithNoRows(t *testing.T) {
  function TestDuplicateRowMiddleRowOfEmptyFile (line 604) | func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
  function TestDuplicateRowWithLargeOffsetToMiddleOfData (line 631) | func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
  function TestDuplicateRowWithLargeOffsetToEmptyRows (line 667) | func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
  function TestDuplicateRowInsertBefore (line 702) | func TestDuplicateRowInsertBefore(t *testing.T) {
  function TestDuplicateRowInsertBeforeWithLargeOffset (line 739) | func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
  function TestDuplicateRowInsertBeforeWithMergeCells (line 775) | func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) {
  function TestDuplicateRowInvalidRowNum (line 807) | func TestDuplicateRowInvalidRowNum(t *testing.T) {
  function TestDuplicateRow (line 867) | func TestDuplicateRow(t *testing.T) {
  function TestDuplicateRowTo (line 927) | func TestDuplicateRowTo(t *testing.T) {
  function TestDuplicateMergeCells (line 946) | func TestDuplicateMergeCells(t *testing.T) {
  function TestGetValueFromInlineStr (line 956) | func TestGetValueFromInlineStr(t *testing.T) {
  function TestGetValueFromNumber (line 965) | func TestGetValueFromNumber(t *testing.T) {
  function TestErrSheetNotExistError (line 986) | func TestErrSheetNotExistError(t *testing.T) {
  function TestCheckRow (line 990) | func TestCheckRow(t *testing.T) {
  function TestSetRowStyle (line 1003) | func TestSetRowStyle(t *testing.T) {
  function TestSetRowHeight (line 1035) | func TestSetRowHeight(t *testing.T) {
  function TestNumberFormats (line 1051) | func TestNumberFormats(t *testing.T) {
  function TestCellXMLHandler (line 1149) | func TestCellXMLHandler(t *testing.T) {
  function BenchmarkRows (line 1209) | func BenchmarkRows(b *testing.B) {
  function trimSliceSpace (line 1231) | func trimSliceSpace(s []string) []string {

FILE: shape.go
  function parseShapeOptions (line 21) | func parseShapeOptions(opts *Shape) (*Shape, error) {
  method AddShape (line 288) | func (f *File) AddShape(sheet string, opts *Shape) error {
  method cellAnchorShape (line 324) | func (f *File) cellAnchorShape(sheet, drawingXML, cell string, width, he...
  method addDrawingShape (line 363) | func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *Sha...
  function setShapeRef (line 509) | func setShapeRef(color string, i int) *aRef {

FILE: shape_test.go
  function TestAddShape (line 10) | func TestAddShape(t *testing.T) {
  function TestAddDrawingShape (line 97) | func TestAddDrawingShape(t *testing.T) {

FILE: sheet.go
  type IgnoredErrorsType (line 32) | type IgnoredErrorsType
  constant IgnoredErrorsEvalError (line 36) | IgnoredErrorsEvalError = iota
  constant IgnoredErrorsTwoDigitTextYear (line 37) | IgnoredErrorsTwoDigitTextYear
  constant IgnoredErrorsNumberStoredAsText (line 38) | IgnoredErrorsNumberStoredAsText
  constant IgnoredErrorsFormula (line 39) | IgnoredErrorsFormula
  constant IgnoredErrorsFormulaRange (line 40) | IgnoredErrorsFormulaRange
  constant IgnoredErrorsUnlockedFormula (line 41) | IgnoredErrorsUnlockedFormula
  constant IgnoredErrorsEmptyCellReference (line 42) | IgnoredErrorsEmptyCellReference
  constant IgnoredErrorsListDataValidation (line 43) | IgnoredErrorsListDataValidation
  constant IgnoredErrorsCalculatedColumn (line 44) | IgnoredErrorsCalculatedColumn
  method NewSheet (line 51) | func (f *File) NewSheet(sheet string) (int, error) {
  method contentTypesReader (line 84) | func (f *File) contentTypesReader() (*xlsxTypes, error) {
  method contentTypesWriter (line 99) | func (f *File) contentTypesWriter() {
  method getWorksheetPath (line 110) | func (f *File) getWorksheetPath(relTarget string) (path string) {
  method mergeExpandedCols (line 120) | func (f *File) mergeExpandedCols(ws *xlsxWorksheet) {
  method workSheetWriter (line 153) | func (f *File) workSheetWriter() {
  function trimRow (line 194) | func trimRow(sheetData *xlsxSheetData) []xlsxRow {
  function trimCell (line 214) | func trimCell(row xlsxRow) xlsxRow {
  method setContentTypes (line 236) | func (f *File) setContentTypes(partName, contentType string) error {
  method setSheet (line 251) | func (f *File) setSheet(index int, name string) {
  method relsWriter (line 266) | func (f *File) relsWriter() {
  function replaceRelationshipsBytes (line 282) | func replaceRelationshipsBytes(content []byte) []byte {
  method SetActiveSheet (line 292) | func (f *File) SetActiveSheet(index int) {
  method GetActiveSheetIndex (line 339) | func (f *File) GetActiveSheetIndex() (index int) {
  method getActiveSheetID (line 355) | func (f *File) getActiveSheetID() int {
  method SetSheetName (line 376) | func (f *File) SetSheetName(source, target string) error {
  method GetSheetName (line 408) | func (f *File) GetSheetName(index int) (name string) {
  method getSheetID (line 421) | func (f *File) getSheetID(sheet string) int {
  method GetSheetIndex (line 433) | func (f *File) GetSheetIndex(sheet string) (int, error) {
  method GetSheetMap (line 460) | func (f *File) GetSheetMap() map[int]string {
  method GetSheetList (line 473) | func (f *File) GetSheetList() (list []string) {
  method getSheetMap (line 485) | func (f *File) getSheetMap() (map[string]string, error) {
  method getSheetXMLPath (line 516) | func (f *File) getSheetXMLPath(sheet string) (string, bool) {
  method SetSheetBackground (line 533) | func (f *File) SetSheetBackground(sheet, picture string) error {
  method SetSheetBackgroundFromBytes (line 546) | func (f *File) SetSheetBackgroundFromBytes(sheet, extension string, pict...
  method setSheetBackground (line 555) | func (f *File) setSheetBackground(sheet, extension string, file []byte) ...
  method DeleteSheet (line 576) | func (f *File) DeleteSheet(sheet 
Condensed preview — 115 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,939K chars).
[
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "chars": 5267,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 21542,
    "preview": "# Contributing to excelize\n\nWant to hack on excelize? Awesome! This page contains information about reporting issues as "
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 143,
    "preview": "github: xuri\nopen_collective: excelize\npatreon: xuri\nko_fi: xurime\nliberapay: xuri\nissuehunt: xuri\ncustom: https://www.p"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 2241,
    "preview": "name: Bug report\ndescription: Create a report to help us improve\nbody:\n  - type: markdown\n    attributes:\n      value: |"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 28,
    "preview": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 1083,
    "preview": "name: Feature request\ndescription: Suggest an idea for this project\nbody:\n  - type: markdown\n    attributes:\n      value"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 1667,
    "preview": "# PR Details\n\n<!--- Provide a general summary of your changes in the Title above -->\n\n## Description\n\n<!--- Describe you"
  },
  {
    "path": ".github/SECURITY.md",
    "chars": 821,
    "preview": "# Security Policy\n\n## Supported Versions\n\nWe will dive into any security-related issue as long as your Excelize version "
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 119,
    "preview": "version: 2\nupdates:\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 666,
    "preview": "name: \"CodeQL\"\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    branches: [master]\n  schedule:\n    - cron: '0 6 *"
  },
  {
    "path": ".github/workflows/go.yml",
    "chars": 1193,
    "preview": "on: [push, pull_request]\nname: build\njobs:\n\n  test:\n    strategy:\n      matrix:\n        go-version: [1.25.x, 1.26.x]\n   "
  },
  {
    "path": ".gitignore",
    "chars": 214,
    "preview": ".DS_Store\n.idea\n*.json\n*.out\n*.test\n~$*.xlsx\ntest/*.png\ntest/BadWorkbook.SaveAsEmptyStruct.xlsx\ntest/Encryption*.xlsx\nte"
  },
  {
    "path": "LICENSE",
    "chars": 1567,
    "preview": "BSD 3-Clause License\n\nCopyright (c) 2016-2026 The excelize Authors.\nCopyright (c) 2011-2017 Geoffrey J. Teale\nAll rights"
  },
  {
    "path": "README.md",
    "chars": 7865,
    "preview": "<p align=\"center\"><img width=\"650\" src=\"./excelize.svg\" alt=\"Excelize logo\"></p>\n\n<p align=\"center\">\n    <a href=\"https:"
  },
  {
    "path": "README_zh.md",
    "chars": 6800,
    "preview": "<p align=\"center\"><img width=\"650\" src=\"./excelize.svg\" alt=\"Excelize logo\"></p>\n\n<p align=\"center\">\n    <a href=\"https:"
  },
  {
    "path": "adjust.go",
    "chars": 37052,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "adjust_test.go",
    "chars": 48753,
    "preview": "package excelize\n\nimport (\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t_ \"image/jpeg\"\n\n\t\"github.com/"
  },
  {
    "path": "calc.go",
    "chars": 619097,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "calc_test.go",
    "chars": 334621,
    "preview": "package excelize\n\nimport (\n\t\"container/list\"\n\t\"math\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testi"
  },
  {
    "path": "calcchain.go",
    "chars": 3814,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "calcchain_test.go",
    "chars": 1707,
    "preview": "package excelize\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestCalcChainReader(t *testing.T) {"
  },
  {
    "path": "cell.go",
    "chars": 50931,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "cell_test.go",
    "chars": 48151,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t_ \"image/jpeg\"\n\t\"math\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync"
  },
  {
    "path": "chart.go",
    "chars": 45133,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "chart_test.go",
    "chars": 43468,
    "preview": "package excelize\n\nimport (\n\t\"bytes\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/as"
  },
  {
    "path": "col.go",
    "chars": 28227,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "col_test.go",
    "chars": 21812,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/"
  },
  {
    "path": "crypt.go",
    "chars": 32108,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "crypt_test.go",
    "chars": 8590,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "datavalidation.go",
    "chars": 18870,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "datavalidation_test.go",
    "chars": 14186,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "date.go",
    "chars": 7559,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "date_test.go",
    "chars": 4154,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\ntype dateTest struct {\n\tE"
  },
  {
    "path": "docProps.go",
    "chars": 13670,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "docProps_test.go",
    "chars": 7210,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "drawing.go",
    "chars": 53356,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "drawing_test.go",
    "chars": 2146,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "errors.go",
    "chars": 19161,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "errors_test.go",
    "chars": 802,
    "preview": "package excelize\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNewInvalidColNameError(t *testi"
  },
  {
    "path": "excelize.go",
    "chars": 21072,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "excelize_test.go",
    "chars": 73122,
    "preview": "package excelize\n\nimport (\n\t\"archive/zip\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"image/color\"\n\t_ \"image/gif\""
  },
  {
    "path": "file.go",
    "chars": 8034,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "file_test.go",
    "chars": 8161,
    "preview": "package excelize\n\nimport (\n\t\"archive/zip\"\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"io\"\n\t\"io/fs\"\n\t\"math\"\n\t\"os\"\n\t\""
  },
  {
    "path": "go.mod",
    "chars": 569,
    "preview": "module github.com/xuri/excelize/v2\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/richardlehane/mscfb v1.0.6\n\tgithub.com/stretchr/tes"
  },
  {
    "path": "go.sum",
    "chars": 2420,
    "preview": "github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.m"
  },
  {
    "path": "hsl.go",
    "chars": 3722,
    "preview": "// Copyright (c) 2012 Rodrigo Moraes. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with"
  },
  {
    "path": "lib.go",
    "chars": 30276,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "lib_test.go",
    "chars": 12774,
    "preview": "package excelize\n\nimport (\n\t\"archive/zip\"\n\t\"bytes\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sy"
  },
  {
    "path": "merge.go",
    "chars": 7262,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "merge_test.go",
    "chars": 7059,
    "preview": "package excelize\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestMergeCell(t *t"
  },
  {
    "path": "numfmt.go",
    "chars": 367133,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "numfmt_test.go",
    "chars": 441707,
    "preview": "package excelize\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/xuri/nfp\"\n)\n\nfunc TestNumFmt(t"
  },
  {
    "path": "picture.go",
    "chars": 37784,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "picture_test.go",
    "chars": 36867,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"image\"\n\t_ \"image/gif\"\n\t_ \"image/jpeg\"\n\t_ \"image/png\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\""
  },
  {
    "path": "pivotTable.go",
    "chars": 35738,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "pivotTable_test.go",
    "chars": 25822,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/ass"
  },
  {
    "path": "rows.go",
    "chars": 28961,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "rows_test.go",
    "chars": 41393,
    "preview": "package excelize\n\nimport (\n\t\"bytes\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"testing\"\n\n\t\"github.com/stretchr"
  },
  {
    "path": "shape.go",
    "chars": 16823,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "shape_test.go",
    "chars": 3953,
    "preview": "package excelize\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestAddShape(t *te"
  },
  {
    "path": "sheet.go",
    "chars": 73079,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "sheet_test.go",
    "chars": 33162,
    "preview": "package excelize\n\nimport (\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n"
  },
  {
    "path": "sheetpr.go",
    "chars": 7270,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "sheetpr_test.go",
    "chars": 4194,
    "preview": "package excelize\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSetPageMargins(t *testing.T) {\n"
  },
  {
    "path": "sheetview.go",
    "chars": 3964,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "sheetview_test.go",
    "chars": 1777,
    "preview": "package excelize\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSetView(t *testing.T) {\n\tf := N"
  },
  {
    "path": "slicer.go",
    "chars": 36734,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "slicer_test.go",
    "chars": 26362,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testi"
  },
  {
    "path": "sparkline.go",
    "chars": 24078,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "sparkline_test.go",
    "chars": 10671,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestAddSpar"
  },
  {
    "path": "stream.go",
    "chars": 24932,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "stream_test.go",
    "chars": 18438,
    "preview": "package excelize\n\nimport (\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"math/rand\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing"
  },
  {
    "path": "styles.go",
    "chars": 121996,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "styles_test.go",
    "chars": 33680,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n"
  },
  {
    "path": "table.go",
    "chars": 21096,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "table_test.go",
    "chars": 9333,
    "preview": "package excelize\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc "
  },
  {
    "path": "templates.go",
    "chars": 69243,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "vml.go",
    "chars": 38751,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "vmlDrawing.go",
    "chars": 11837,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "vml_test.go",
    "chars": 23121,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "workbook.go",
    "chars": 14192,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "workbook_test.go",
    "chars": 2960,
    "preview": "package excelize\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWorkbookProps(t *testing.T) {\n\t"
  },
  {
    "path": "xmlApp.go",
    "chars": 2955,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlCalcChain.go",
    "chars": 6592,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlChart.go",
    "chars": 26126,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlChartSheet.go",
    "chars": 4195,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlComments.go",
    "chars": 3525,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlContentTypes.go",
    "chars": 1534,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlCore.go",
    "chars": 4239,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlCustom.go",
    "chars": 4979,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlDecodeDrawing.go",
    "chars": 12848,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlDrawing.go",
    "chars": 19397,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlMetaData.go",
    "chars": 5823,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlPivotCache.go",
    "chars": 11993,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlPivotTable.go",
    "chars": 16596,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlSharedStrings.go",
    "chars": 3798,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlSlicers.go",
    "chars": 8525,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlStyles.go",
    "chars": 15098,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlTable.go",
    "chars": 11938,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlTheme.go",
    "chars": 10291,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlWorkbook.go",
    "chars": 20025,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  },
  {
    "path": "xmlWorksheet.go",
    "chars": 58211,
    "preview": "// Copyright 2016 - 2026 The excelize Authors. All rights reserved. Use of\n// this source code is governed by a BSD-styl"
  }
]

// ... and 13 more files (download for full content)

About this extraction

This page contains the full source code of the qax-os/excelize GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 115 files (3.4 MB), approximately 900.4k tokens, and a symbol index with 3163 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!