qax-os / excelize

Go language library for reading and writing Microsoft Excel™ (XLAM / XLSM / XLSX / XLTM / XLTX) spreadsheets
https://xuri.me/excelize
BSD 3-Clause "New" or "Revised" License
18.43k stars 1.73k forks source link

Add support for setting the classic layout for pivot table #1993

Closed Zncl2222 closed 2 months ago

Zncl2222 commented 2 months ago

Description

It seems that excelize does not support setting the classic layout for pivot tables currently.

image

Howevere I needed this function, so I made some adjustments to implement it.

You can find implementation here:

https://github.com/Zncl2222/excelize/commit/5f7a4ce4ada6c5150e56d4a9e4c9103f640d6e75

The classic layout need to set Compact and CompactData to false, set GridDropZones to true in PivotTableDefinition, and set Outline and Compact in each field to false

I am happy to submit a PR if you find this idea valuable. If you approve this proposal, I will modify the commit message to follow the style of excelize's commit messages and add more test cases if needed.

Example

In this implementation https://github.com/Zncl2222/excelize/commit/5f7a4ce4ada6c5150e56d4a9e4c9103f640d6e75, user only need to set the ClassicLayout to true in PivotTableOptions to configure the pivot table in classic layout.

The code snippet to create the pivot table with classic layout

package main

import (
    "fmt"

    "github.com/xuri/excelize/v2"

    "golang.org/x/exp/rand"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    month := []string{"Jan", "Feb", "Mar", "Apr", "May",
        "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
    year := []int{2017, 2018, 2019}
    types := []string{"Meat", "Dairy", "Beverages", "Produce"}
    region := []string{"East", "West", "North", "South"}
    f.SetSheetRow("Sheet1", "A1", &[]string{"Month", "Year", "Type", "Sales", "Region"})
    for row := 2; row < 32; row++ {
        f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), month[rand.Intn(12)])
        f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), year[rand.Intn(3)])
        f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), types[rand.Intn(4)])
        f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), rand.Intn(5000))
        f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), region[rand.Intn(4)])
    }

    if err := f.AddPivotTable(&excelize.PivotTableOptions{
        DataRange:       "Sheet1!A1:E31",
        PivotTableRange: "Sheet1!G2:M34",
        Rows: []excelize.PivotTableField{
            {Data: "Month", Name: "I Am Month", DefaultSubtotal: true}, {Data: "Year", Name: "I Am Year"}},
        Filter: []excelize.PivotTableField{
            {Data: "Region"}},
        Columns: []excelize.PivotTableField{
            {Data: "Type", DefaultSubtotal: true, Name: "I Am Columns"}},
        Data: []excelize.PivotTableField{
            {Data: "Sales", Name: "Summarize", Subtotal: "Sum"}},
        RowGrandTotals: true,
        ColGrandTotals: true,
        ShowDrill:      true,
        ShowRowHeaders: true,
        ShowColHeaders: true,
        ShowLastColumn: true,
        ClassicLayout:  true,
    }); err != nil {
        fmt.Println(err)
        return
    }

    if err := f.SaveAs("PivotTable.xlsx"); err != nil {
        fmt.Println(err)
    }
}

image

If the ClassicLayout property is unset or set to false, the pivot table will look like this:

image

xuri commented 2 months ago

Thanks for your issue. I have added get and set pivot table classical layout support by referenced your code. Please upgrade the master branch code by go get -u github.com/xuri/excelize/v2@master, and this feature will be released in the next version.