Golang library for reading and writing Microsoft Excel™ (XLSX) files.

Excelize logo

Build Status Code Coverage Go Report Card go.dev Licenses Donate

Excelize

Introduction

Excelize is a library written in pure Go providing a set of functions that allow you to write to and read from XLSX / XLSM / XLTM 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.10 or later. The full API docs can be seen using go's built-in documentation tool, or online at go.dev and docs reference.

Basic Usage

Installation

go get github.com/360EntSecGroup-Skylar/excelize
  • If your packages are managed using Go Modules, please install with following command.
go get github.com/360EntSecGroup-Skylar/excelize/v2

Create spreadsheet

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

package main

import (
    "fmt"

    "github.com/360EntSecGroup-Skylar/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    // Create a new sheet.
    index := f.NewSheet("Sheet2")
    // 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.

package main

import (
    "fmt"

    "github.com/360EntSecGroup-Skylar/excelize/v2"
)

func main() {
    f, err := excelize.OpenFile("Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    // Get value from cell by given worksheet name and axis.
    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")
    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.

Excelize

package main

import (
    "fmt"

    "github.com/360EntSecGroup-Skylar/excelize/v2"
)

func main() {
    categories := map[string]string{
        "A2": "Small", "A3": "Normal", "A4": "Large",
        "B1": "Apple", "C1": "Orange", "D1": "Pear"}
    values := map[string]int{
        "B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
    f := excelize.NewFile()
    for k, v := range categories {
        f.SetCellValue("Sheet1", k, v)
    }
    for k, v := range values {
        f.SetCellValue("Sheet1", k, v)
    }
    if err := f.AddChart("Sheet1", "E1", `{
        "type": "col3DClustered",
        "series": [
        {
            "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":
        {
            "name": "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

package main

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

    "github.com/360EntSecGroup-Skylar/excelize/v2"
)

func main() {
    f, err := excelize.OpenFile("Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    // Insert a picture.
    if err := f.AddPicture("Sheet1", "A2", "image.png", ""); err != nil {
        fmt.Println(err)
    }
    // Insert a picture to worksheet with scaling.
    if err := f.AddPicture("Sheet1", "D2", "image.jpg",
        `{"x_scale": 0.5, "y_scale": 0.5}`); err != nil {
        fmt.Println(err)
    }
    // Insert a picture offset in the cell with printing support.
    if err := f.AddPicture("Sheet1", "H2", "image.gif", `{
        "x_offset": 15,
        "y_offset": 10,
        "print_obj": true,
        "lock_aspect_ratio": false,
        "locked": false
    }`); 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.

Licenses

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

The Excel logo is a trademark of Microsoft Corporation. This artwork is an adaptation.

gopher.{ai,svg,png} was created by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license.

Owner
360 Enterprise Security Group, Endpoint Security, inc.
360企业安全集团终端安全子公司
360 Enterprise Security Group, Endpoint Security, inc.
Comments
  • PR 366 Documentation

    PR 366 Documentation

    Description

    #366 Removed ToAlphaString, which is a breaking change, and replaced it with ColumnNumberToName. The documentation however, still has the original name in it. It also changed the signature from a string return value to a (string, error) return value to guard against indexes less than one. This doesn't seem necessary.

    It also appears to have changed the zero based index to a one based index. What was the motivation for these changes?

    Will there be a changelog that lays out other things that are now broken from that PR? It would be helpful to know what the upgrade path looks like.

  • macOS can not use

    macOS can not use

    cell := xlsx.GetCellValue("Sheet1", "B2") fmt.Println(cell) // Get all the rows in a sheet. rows := xlsx.GetRows("sheet1") fmt.Println(rows)

    in windows it works normal,but in macOS rows is empty,cell can get value

  • When Edit excel file,show warning

    When Edit excel file,show warning "发现“22.xlsx”中的部分内容有问题。是否让我们尽量尝试恢复? 如果您信任此工作簿的源,请单击“是”。"

    Description when edit the excel file with excelize , show the warning "发现“22.xlsx”中的部分内容有问题。是否让我们尽量尝试恢复? 如果您信任此工作簿的源,请单击“是"。"

    Steps to reproduce the issue:

    1. create a empty excel file,saved as "22.xlsx"

    2. use code edit it .

      f, _ := excelize.OpenFile("/Users/dev/Downloads/22.xlsx") f.SetActiveSheet(0) sheetName := f.GetSheetName(0) fmt.Println(sheetName) er := f.SetCellDefault(sheetName, "C4", "test") fmt.Println(er) f.Save()

    3. open the 22.xlsx file

    Describe the results you received:

    Describe the results you expected:

    Output of go version:

    go version go1.16.4 darwin/amd64
    

    Excelize version or commit ID:

    excelize 2.4.1
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.): macOS Big Sur 11.4 Go 1.16.4 excelize 2.4.1 Excel 16.29(19090802)

  • SetColStyle not honoring given style

    SetColStyle not honoring given style

    Description SetColStyle seems to be corrupting spreadsheets. It doesn't seem to matter what data is in the column or which column or sheet you use.

    I created this simple code to re-produce it:

    package main
    
    import (
    	"github.com/excelize"
    )
    
    // define globals
    
    var xlfile = "testlocal.xlsx"
    var xlsheetname = "test"
    
    // main
    func main() {
    	var (
    		file *excelize.File
    		err  error
    	)
    	// open the file
    	file, err = excelize.OpenFile(xlfile)
    	errorhandler(err)
    
    	err = file.SetColStyle(xlsheetname, "C", 7)
    	errorhandler(err)
    	file.Save()
    
    }
    
    func errorhandler(e error) {
    	if e != nil {
    		panic(e)
    	}
    }
    

    Steps to reproduce the issue:

    1. Create a spreadsheet named localtest.xlsx and a sheet named test
    2. run this test code against it
    3. open the spreadsheet and see it needs repair

    Describe the results you received: image Repair Log: `

    Repair Result to testlocal5.xml

    Errors were detected in file '/Users/stalt/Documents/go/src/setcoltest/testlocal.xlsx'Repaired Records: Column information from /xl/worksheets/sheet1.xml part

    `

    Describe the results you expected: I expect the column to be formated with

    Output of go version:

    $ go version
    go version go1.10 darwin/amd64
    

    Excelize version or commit ID:

    commit id: 448f552
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.): macOS Mojave 10.14.5 Excel for Mac 16.27 (19071500)

  • On same Exceltables different amount of columns detected

    On same Exceltables different amount of columns detected

    Hello on some excel tables i have a diffrenet amount of columns:

    https://imgur.com/a/s7TrBJK

    in this excel files i have different types of field. text, floats, urls, bools and so on. also stuff with commas and semicolons and this thing here -> '

    the file is imported from csv to excel and then save as xlsx. but i cant opet and work with excel in numbers or in excel so should not be an file error.

    thats how i read it... row, _ := file.GetRows(file.GetSheetName(0))

  • after saving, file looks different

    after saving, file looks different

    1. open xlsx (quite complex formatting - styles and etc)
    2. copy from Col A into Col B
    3. set Col A equal 0
    4. save as a new file - files looks different :(

    some cells at each row can be merged, BUT Col A, and Col B are simple - only style formatting.

    More overs, some rows(quite a lot) that I'm not updating - after saving looks different.

    Let's recap - I only update some simple cells at some rows. Why rows that I'm not touching looks different?! :(

  •  Call GetSheetName can not get correct sheetname

    Call GetSheetName can not get correct sheetname

    Description

    GetSheetName can not get correct sheet name just return empty string

    Steps to reproduce the issue:

    1. my xlsx file's first sheet named "basic". so I call GetSheetIndex("basic") get return value is 15
    2. call GetSheetName(15) return value is "" (empty string)

    Describe the results you received: I get an empty string as sheetname

    Describe the results you expected: I expect the return string should be "basic"

    Output of go version:

    go version go1.11 linux/amd64
    

    Excelize version or commit ID:

    eef232f09ecd41b1f8fc199906ce0be64865802e
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.):

    Ubuntu 18.04, wps 2019( can open and eidt excel 2007 xlsx file), thinkpad x1 carbon
    
  • Performance of large files is really bad

    Performance of large files is really bad

    I see your performance metrics in the docs but the files i'm dealing with can often be up to half a million rows.

    I'm importing from a CSV and as I continually SetCellValues processing each line, the performance of adding those lines gets worse and worse.

    	reader := csv.NewReader(csvBody)
    	const headerRow = 1
    	row := headerRow
    	var headers []string
    	rowstart := time.Now()
    	for {
    		line, err := reader.Read()
    		if err == io.EOF {
    			break
    		} else if err != nil {
    			log.Printf("Error Reading CSV: %+v ", err)
    			return err
    		}
    		if row == headerRow {
    			headers = line
    		}
    		for cellIndex, cellValue := range line {
    			if row > headerRow && stringInSlice(headers[cellIndex], []string{"quantity", "price"}) {
    				cellParsedValue, err := strconv.ParseFloat(cellValue, 64)
    				if err != nil {
    					log.Printf("%s\ncell %d in line %d had invalid value %s", err, cellIndex, row, cellValue)
    					return err
    				}
    				xlsx.SetCellValue("details", fmt.Sprintf("%s%d", excelize.ToAlphaString(cellIndex), row), cellParsedValue)
    			} else {
    				xlsx.SetCellValue("details", fmt.Sprintf("%s%d", excelize.ToAlphaString(cellIndex), row), cellValue)
    			}
    
    		}
    		pow10row := findPow10(row)
    		if row <= pow10row*10 && (row%pow10row == 0 || row%10000 == 0) {
    			elapsed := time.Since(rowstart)
    			log.Printf("Row %d, time elapsed %s", row, elapsed)
    			rowstart = time.Now()
    		}
    		row++
    	}
    

    Describe the results you received: In the log output below, each time elapsed is the difference from the previous log line. you can see that after about 10,000 rows, its starting to get really bad in terms of how long it takes to process each next 10,000 rows.

    2019/04/08 21:38:37 Row 1, time elapsed 1.505084ms
    2019/04/08 21:38:37 Row 2, time elapsed 96.097µs
    2019/04/08 21:38:37 Row 3, time elapsed 101.482µs
    2019/04/08 21:38:37 Row 4, time elapsed 94.35µs
    2019/04/08 21:38:37 Row 5, time elapsed 94.585µs
    2019/04/08 21:38:37 Row 6, time elapsed 96.621µs
    2019/04/08 21:38:37 Row 7, time elapsed 97.552µs
    2019/04/08 21:38:37 Row 8, time elapsed 99.631µs
    2019/04/08 21:38:37 Row 9, time elapsed 108.849µs
    2019/04/08 21:38:37 Row 10, time elapsed 74.078µs
    2019/04/08 21:38:37 Row 20, time elapsed 545.239µs
    2019/04/08 21:38:37 Row 30, time elapsed 513.501µs
    2019/04/08 21:38:37 Row 40, time elapsed 532.816µs
    2019/04/08 21:38:37 Row 50, time elapsed 564.326µs
    2019/04/08 21:38:37 Row 60, time elapsed 669.845µs
    2019/04/08 21:38:37 Row 70, time elapsed 1.508732ms
    2019/04/08 21:38:37 Row 80, time elapsed 666.172µs
    2019/04/08 21:38:37 Row 90, time elapsed 594.624µs
    2019/04/08 21:38:37 Row 100, time elapsed 630.948µs
    2019/04/08 21:38:37 Row 200, time elapsed 7.519094ms
    2019/04/08 21:38:37 Row 300, time elapsed 6.852758ms
    2019/04/08 21:38:37 Row 400, time elapsed 8.674476ms
    2019/04/08 21:38:37 Row 500, time elapsed 8.159781ms
    2019/04/08 21:38:37 Row 600, time elapsed 9.568621ms
    2019/04/08 21:38:37 Row 700, time elapsed 8.916284ms
    2019/04/08 21:38:37 Row 800, time elapsed 10.846477ms
    2019/04/08 21:38:37 Row 900, time elapsed 9.282789ms
    2019/04/08 21:38:37 Row 1000, time elapsed 12.92103ms
    2019/04/08 21:38:37 Row 2000, time elapsed 128.488664ms
    2019/04/08 21:38:37 Row 3000, time elapsed 189.107883ms
    2019/04/08 21:38:37 Row 4000, time elapsed 278.586948ms
    2019/04/08 21:38:38 Row 5000, time elapsed 391.341065ms
    2019/04/08 21:38:38 Row 6000, time elapsed 471.830863ms
    2019/04/08 21:38:39 Row 7000, time elapsed 530.416468ms
    2019/04/08 21:38:39 Row 8000, time elapsed 602.603427ms
    2019/04/08 21:38:40 Row 9000, time elapsed 652.277227ms
    2019/04/08 21:38:41 Row 10000, time elapsed 729.849772ms
    2019/04/08 21:38:52 Row 20000, time elapsed 10.977776474s
    2019/04/08 21:39:10 Row 30000, time elapsed 18.55464695s
    2019/04/08 21:39:37 Row 40000, time elapsed 26.336721766s
    2019/04/08 21:40:10 Row 50000, time elapsed 33.489274657s
    2019/04/08 21:40:51 Row 60000, time elapsed 40.729296603s
    2019/04/08 21:41:39 Row 70000, time elapsed 47.928431496s
    2019/04/08 21:42:34 Row 80000, time elapsed 55.148409674s
    2019/04/08 21:43:36 Row 90000, time elapsed 1m2.4532031s
    2019/04/08 21:44:46 Row 100000, time elapsed 1m9.608536367s
    2019/04/08 21:46:03 Row 110000, time elapsed 1m16.990387462s
    2019/04/08 21:47:27 Row 120000, time elapsed 1m24.146257207s
    2019/04/08 21:48:59 Row 130000, time elapsed 1m31.308584865s
    2019/04/08 21:50:37 Row 140000, time elapsed 1m38.654884213s
    2019/04/08 21:52:23 Row 150000, time elapsed 1m46.000199696s
    2019/04/08 21:54:16 Row 160000, time elapsed 1m53.238934707s
    2019/04/08 21:56:17 Row 170000, time elapsed 2m0.485714266s
    2019/04/08 21:58:25 Row 180000, time elapsed 2m7.897305904s
    2019/04/08 22:00:40 Row 190000, time elapsed 2m15.234462928s
    2019/04/08 22:03:03 Row 200000, time elapsed 2m23.134322152s
    2019/04/08 22:05:34 Row 210000, time elapsed 2m30.40930936s
    2019/04/08 22:08:11 Row 220000, time elapsed 2m37.873410076s
    2019/04/08 22:10:59 Row 230000, time elapsed 2m47.92659603s
    2019/04/08 22:13:58 Row 240000, time elapsed 2m58.625053178s
    2019/04/08 22:17:08 Row 250000, time elapsed 3m10.348595584s
    2019/04/08 22:20:29 Row 260000, time elapsed 3m20.726383957s
    2019/04/08 22:24:08 Row 270000, time elapsed 3m38.840478421s
    2019/04/08 22:28:12 Row 280000, time elapsed 4m4.294031488s
    2019/04/08 22:32:43 Row 290000, time elapsed 4m30.85305806s
    2019/04/08 22:37:45 Row 300000, time elapsed 5m2.183625905s
    2019/04/08 22:43:18 Row 310000, time elapsed 5m33.135633645s
    2019/04/08 22:49:22 Row 320000, time elapsed 6m3.47749514s
    2019/04/08 22:55:56 Row 330000, time elapsed 6m33.647828s
    2019/04/08 23:02:59 Row 340000, time elapsed 7m3.546443285s
    2019/04/08 23:10:35 Row 350000, time elapsed 7m35.978277292s
    2019/04/08 23:18:43 Row 360000, time elapsed 8m8.039533099s
    2019/04/08 23:27:22 Row 370000, time elapsed 8m38.447390938s
    2019/04/08 23:36:33 Row 380000, time elapsed 9m11.603785808s
    2019/04/08 23:46:15 Row 390000, time elapsed 9m41.515021912s
    2019/04/08 23:56:17 Row 400000, time elapsed 10m2.085553551s
    2019-04-09
    2019/04/09 00:06:42 Row 410000, time elapsed 10m25.252517462s
    2019/04/09 00:17:38 Row 420000, time elapsed 10m55.909756693s
    

    Describe the results you expected:

    if there was a direct way to import a CSV or some method to speed this sort of import up, it would be really useful

    Excelize version or commit ID:

      digest = "1:9b67e96a030cc96a3bef1d7cb1143f1e13440f1087eee5999fa9ba5514c1027c"
      name = "github.com/360EntSecGroup-Skylar/excelize"
      packages = ["."]
      pruneopts = ""
      revision = "dea7ba0ec43a4c29a6642d02b6edc73b8b0369f0"
      version = "v1.4.1"
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.): The above log was captured from an AWS Fargate Docker task running with 4096 CPU units and 30720 MiB

  • Write to file as stream row by row?

    Write to file as stream row by row?

    Hi, would it be possible to have something like stream-writing to a file in case of lots of rows? Like hitting the excel sheet row limit?

    I'm not so familiar with GoLang's IO, but maybe there is no problem to achieve this?

    For example I have millions of rows to put in excel sheets, and it is obviously memory heavy task. The idea is to read slice of rows from data source, like 100,000 at the time, then write them to the excel file in a loop until all rows was written. In such case there would be produced either excel file with few sheets or few excel files.

    The primary idea is to handle memory consumption to reasonable amounts of RAM, like few gigabytes not tens..

    What's Your opinion?

  • Corrupted xlsx after write operation

    Corrupted xlsx after write operation

    Thank you for your great work on excelize. Reading works like a charm. But I have an issue with writing.

    I update one cell, save and XLSX file is corrupted.

    Input file: source_file.xlsx Output corrupted file: Workbook.xlsx

    How I am writing to the file

    xlsx, err := excelize.OpenFile(path)
    xlsx.SetCellInt("Sheet1", "I15", 100)
    err := xlsx.SaveAs("./Workbook.xlsx")
    

    Erro message during opening Workbook.xlsx image

    And error if I try to recover the workbook: Replaced Part: /xl/worksheets/sheet1.xml part with XML error. Load error. Line 2, column 213397. Removed Records: Formula from /xl/calcChain.xml part (Calculation properties)

    go env

    set GOARCH=amd64
    set GOBIN=
    set GOEXE=.exe
    set GOHOSTARCH=amd64
    set GOHOSTOS=windows
    set GOOS=windows
    set GOPATH=C:\Users\stanislav.valasek\go
    set GORACE=
    set GOROOT=C:\Go
    set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
    set GCCGO=gccgo
    set CC=gcc
    set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
    set CXX=g++
    set CGO_ENABLED=1
    set CGO_CFLAGS=-g -O2
    set CGO_CPPFLAGS=
    set CGO_CXXFLAGS=-g -O2
    set CGO_FFLAGS=-g -O2
    set CGO_LDFLAGS=-g -O2
    set PKG_CONFIG=pkg-config
    
  • fix-save-to-file-as-stream

    fix-save-to-file-as-stream

    PR Details

    • Change the write method from writing to a bytes.Buffer to writing a stream to io.Writer

    Description

    • create a zip.Writer from io.Writer
    • for each components, create a new file then using a xml.Encoder() and write to io.Writer
    • using custom unmarshalXML to avoid using this block of code
    
    func replaceRelationshipsBytes(content []byte) []byte {
    	oldXmlns := []byte(`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships`)
    	newXmlns := []byte("r")
    	return bytes.Replace(content, oldXmlns, newXmlns, -1)
    }
    

    Related Issue

    https://github.com/360EntSecGroup-Skylar/excelize/issues/487

    Motivation and Context

    improve performance and reduce memory for storing XML data

    How Has This Been Tested

    • writing a unit test for comparing custom unmarshal function and bytes.Replace result

    Types of changes

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

    Checklist

    • [x] My code follows the code style of this project.
    • [ ] My change requires a change to the documentation.
    • [ ] I have updated the documentation accordingly.
    • [x] I have read the CONTRIBUTING document.
    • [x] I have added tests to cover my changes.
    • [x] All new and existing tests passed.
  • CalcCellValue - don't evalutate correct value with Formula IF with other formula inside

    CalcCellValue - don't evalutate correct value with Formula IF with other formula inside

    Description

    Steps to reproduce the issue:

    1. in cell D142 value 2, in cell D143 value 1, in cell D144 value 1, in cell D145 value 2
    2. in cell E142 define formula =AVERAGE(D142:D145)/5
    3. in cell F142 define formula =IF(E142 > 0,4;"major";"minor")

    Describe the results you received: major Describe the results you expected: minor because the value in E142 is 0,3 Output of go version:

    go version go1.19.1 windows/amd64
    

    Excelize version or commit ID:

    b39626fae9c2aaa648259d412a67b67e7768ad17
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.): Windows, Excel

  • Fix panic in getSheetMap

    Fix panic in getSheetMap

    Add missing error checks in getSheetMap

    PR Details

    Missing error checks in getSheetMap

    Description

    Add error checks for getSheetMap

    Related Issue

    Motivation and Context

    There is no error checks, parser can crash on malformed input

    How Has This Been Tested

    Tested against a sample corrupted file

    Types of changes

    • [ ] Docs change / refactoring / dependency upgrade
    • [x] 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

    • [x] My code follows the code style of this project.
    • [ ] My change requires a change to the documentation.
    • [ ] I have updated the documentation accordingly.
    • [x] I have read the CONTRIBUTING document.
    • [x] I have added tests to cover my changes.
    • [x] All new and existing tests passed.
  • CalcCellValue doesn't support function TEXT

    CalcCellValue doesn't support function TEXT

    Description

    Steps to reproduce the issue:

    1. in cell A1 input the value 0.05
    2. in cell A2 define the following formula =TEXT(A1, "0,0%")

    Describe the results you received: unsupported TEXT function

    Output of go version:

    go version go1.19.1 windows/amd64
    

    Excelize version or commit ID:

    b39626fae9c2aaa648259d412a67b67e7768ad17
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.): Windows, Excel

  • CalcCellValue doesn't work as expected with DATEVALUE

    CalcCellValue doesn't work as expected with DATEVALUE

    Description

    I'm using CalcCellValue in order to calculate the value previously set with the SetCellFormula. In this specific case, I am using a DATEVALUE formula. Basically, what I do is something like this:

    err = f.SetCellFormula(firstSheet, "K2", "DATEVALUE(\"2.7.2023\")"))
    if err != nil {
        logger.WithErr(err).Debug("SetCellFormula error")
        return nil, nil, err
    }
    
    cellValue, err = f.CalcCellValue(firstSheet, "K2")
    if err != nil {
        logger.WithErr(err).Debug("CalcCellValue error")
        return nil, nil, err
    }
    

    Describe the results you received:

    From the example above, I will always receive #VALUE! in the err.

    On the other side, I have also tried another simple example and this works as expected aka I receive 1 as a cellValue.

    err = f.SetCellFormula(firstSheet, "K2", "ABS(-1)")
    if err != nil {
        logger.WithErr(err).Debug("SetCellFormula error")
        return nil, nil, err
    }
    					
    cellValue, err = f.CalcCellValue(firstSheet, "K2")
    if err != nil {
        logger.WithErr(err).Debug("CalcCellValue error")
        return nil, nil, err
    }
    

    Is it possible there are some issues just with DATEVALUE or am I doing something wrong?

    Describe the results you expected:

    Instead of error (#VALUE!), I would expect 45109, which is the numeric value received after applying DATEVALUE on the 2.7.2023.

    image

    Output of go version:

    go version go1.19.3 darwin/arm6
    

    Excelize version or commit ID:

    ab12307393461e7055f664d296a3a0e686eebb39
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.):

    MacOS, Excel 16.68

  • picture insert style error

    picture insert style error

    Description when i try to insert more than three pictures in a cell, there is a style mixed in the cell, the third picture will fill the whole cell and the other left picture which are more than 3 their width would be 0

    Steps to reproduce the issue: 1. 2. 3.

    Describe the results you received:

    Describe the results you expected:

    Output of go version:

    (paste your output here)
    

    Excelize version or commit ID:

    (paste here)
    

    Environment details (OS, Microsoft Excel™ version, physical, etc.):

  • #1402 Get CountRows from sheet

    #1402 Get CountRows from sheet

    PR Details

    Get CountRows from sheet

    Description

    Get CountRows from sheet

    Related Issue

    https://github.com/qax-os/excelize/issues/1402

    Motivation and Context

    Current solutions are slow. My solution is fast.

    file 1М rows | - | - | - | |---|---|---| | BenchmarkFile_GetRows_Old-8 | 1 | 5797898958 ns/op | | BenchmarkFile_GetRows_New-8 | 3 | 411330472 ns/op |

    How Has This Been Tested

    Run test TestFile_CountRows

    Types of changes

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

    Checklist

    • [ ] 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.
A Go io/fs filesystem implementation for reading files in a Github gists.

GistFS GistFS is an io/fs implementation that enables to read files stored in a given Gist. Requirements This module depends on io/fs which is only av

Oct 14, 2022
Atomic: a go package for atomic file writing

atomic import "github.com/natefinch/atomic" atomic is a go package for atomic file writing By default, writing to a file in go (and generally any lan

Nov 10, 2021
app-services-go-linter plugin analyze source tree of Go files and validates the availability of i18n strings in *.toml files

app-services-go-linter app-services-go-linter plugin analyze source tree of Go files and validates the availability of i18n strings in *.toml files. A

Nov 29, 2021
Split text files into gzip files with x lines

hakgzsplit split lines of text into multiple gzip files

Jun 21, 2022
Easily create Go files from stub files

go-stubs Easily create .go files from stub files in your projects. Usage go get github.com/nwby/go-stubs Create a stub file: package stubs type {{.Mo

Jan 27, 2022
Golang PDF library for creating and processing PDF files (pure go)

UniPDF - PDF for Go UniDoc UniPDF is a PDF library for Go (golang) with capabilities for creating and reading, processing PDF files. The library is wr

Dec 28, 2022
Vaala archive is a tar archive tool & library optimized for lots of small files.

?? Vaar ?? Vaala archive is a tar archive tool & library optimized for lots of small files. Written in Golang, vaar performs operations in parallel &

Sep 12, 2022
Golang wrapper for Exiftool : extract as much metadata as possible (EXIF, ...) from files (pictures, pdf, office documents, ...)

go-exiftool go-exiftool is a golang library that wraps ExifTool. ExifTool's purpose is to extract as much metadata as possible (EXIF, IPTC, XMP, GPS,

Dec 28, 2022
Load GTFS files in golang

go-gtfs Load GTFS files in Go. The project is in maintenance mode. It is kept compatible with changes in the Go ecosystem but no new features will be

Dec 5, 2022
Merge some files in a path with custom extension in golang
Merge some files in a path with custom extension in golang

goMerge Merge some files in a path with custom extension in golang Feature Walk in a path with a goroutine using parallelism Merge files with custom e

Apr 26, 2022
QueryCSV enables you to load CSV files and manipulate them using SQL queries then after you finish you can export the new values to a CSV file
QueryCSV enables you to load CSV files and manipulate them using SQL queries then after you finish you can export the new values to a CSV file

QueryCSV enable you to load CSV files and manipulate them using SQL queries then after you finish you can export the new values to CSV file

Dec 22, 2021
🏵 Gee is tool of stdin to each files and stdout
🏵 Gee is tool of stdin to each files and stdout

Gee is tool of stdin to each files and stdout. It is similar to the tee command, but there are more functions for convenience. In addition, it was written as go. which provides output to stdout and files.

Nov 17, 2022
Easily create & extract archives, and compress & decompress files of various formats

archiver Introducing Archiver 3.1 - a cross-platform, multi-format archive utility and Go library. A powerful and flexible library meets an elegant CL

Jan 3, 2023
A Go filesystem package for working with files and directories

Stowage A Go filesystem package for working with files and directories, it features a simple API with support for the common files and directories ope

May 28, 2021
🌳 📂 The utility displays a tree of directories and files(symlinks in future).

dirTree The utility displays a tree of directories and files. usage: dirTree [-f] How it works with directory, where I wrote this project for example

Aug 12, 2021
Allows parsing CSV files into custom structs and implements required fields that can't be empty

Welcome to Go Custom CSV Parser ?? Allows parsing CSV files into custom structs and implements required fields that can't be empty ?? Homepage Install

Nov 9, 2021
Utility for working with files and folders stored on Google Drive

skicka Utility for working with files and folders stored on Google Drive. Note: skicka is not an official Google product! Intro skicka makes it easy t

Nov 15, 2021
Provide an upload endpoint that stores files on pinata and returns a json response with the uploaded file pinata url

Purpose Build a template repository to get to coding as quickly as possible, by starting from a common template which follows the guidelines here Feat

Dec 30, 2021