Skip to content

Commit

Permalink
Merge pull request #134 from Zncl2222/Zncl2222/feature/pivot_table
Browse files Browse the repository at this point in the history
Feat: add pivot table
  • Loading branch information
Zncl2222 authored Sep 9, 2024
2 parents 9d010cc + 52c0822 commit c9af95a
Show file tree
Hide file tree
Showing 13 changed files with 897 additions and 52 deletions.
40 changes: 40 additions & 0 deletions docs/pivot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## PivotTableField

Represents a field within a PivotTable, which includes various settings like name,
data, compact display, and subtotal configurations.

| Attribute | Type | Description |
|-------------------|------------------------------------------|-------------------------------------------------------------------|
| `compact` | `Optional[bool]` | Indicates whether the field is displayed in compact form. |
| `data` | `Optional[str]` | The data value associated with the field. |
| `name` | `Optional[str]` | The name of the field. |
| `outline` | `Optional[bool]` | Indicates whether the field is in outline form. |
| `subtotal` | `Optional[str or PivotSubTotal]` | The subtotal type for the field. |
| `default_subtotal`| `Optional[bool]` | Specifies if the field has a default subtotal applied. |

## PivotTable

Represents a PivotTable configuration, including data ranges, field settings, and display options.

| Attribute | Type | Description |
|-----------------------|-----------------------------------------|---------------------------------------------------------------------------------------|
| `data_range` | `str` | Range of data used for the pivot table, e.g., "Sheet1!A1:B2". |
| `pivot_table_range` | `str` | Range where the pivot table will be placed, e.g., "Sheet1!C3:D4". |
| `rows` | `list[PivotTableField]` | List of fields used as rows in the pivot table. |
| `pivot_filter` | `list[PivotTableField]` | List of fields used as filters in the pivot table. |
| `columns` | `list[PivotTableField]` | List of fields used as columns in the pivot table. |
| `data` | `list[PivotTableField]` | List of fields used as data fields in the pivot table. |
| `row_grand_totals` | `Optional[bool]` | Indicates whether to display row grand totals. |
| `column_grand_totals` | `Optional[bool]` | Indicates whether to display column grand totals. |
| `show_drill` | `Optional[bool]` | Indicates whether to show drill indicators. |
| `show_row_headers` | `Optional[bool]` | Indicates whether to display row headers. |
| `show_column_headers` | `Optional[bool]` | Indicates whether to display column headers. |
| `show_row_stripes` | `Optional[bool]` | Indicates whether to display row stripes. |
| `show_col_stripes` | `Optional[bool]` | Indicates whether to display column stripes. |
| `show_last_column` | `Optional[bool]` | Indicates whether to display the last column. |
| `use_auto_formatting` | `Optional[bool]` | Indicates whether to apply automatic formatting. |
| `page_over_then_down` | `Optional[bool]` | Indicates whether pages should be ordered top-to-bottom, then left-to-right. |
| `merge_item` | `Optional[bool]` | Indicates whether to merge items in the pivot table. |
| `compact_data` | `Optional[bool]` | Indicates whether to display data in compact form. |
| `show_error` | `Optional[bool]` | Indicates whether to display errors. |
| `pivot_table_style_name` | `Optional[str]` | Specifies the style for the pivot table, chosen from a predefined set of styles. |
87 changes: 87 additions & 0 deletions docs/workbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,90 @@ wb.add_chart(
legend=ChartLegendModel(position='top', show_legend_key=True),
)
```

## Add Pivot Table

This function allows you to add a pivot table to a worksheet using either a `PivotTable` object or by specifying ranges and fields directly. You can customize the appearance and functionality of the pivot table using various optional parameters.

!!! note "Note"
- You can either pass a `PivotTable` object or directly specify the data range, pivot table range, and fields.
- Ensure that the data range and pivot table range are correctly formatted and within the sheet's valid boundaries.
- Optional parameters allow you to control the visibility of row and column headers, grand totals, stripes, and more.

### Adding a Pivot Table Using a `PivotTable` Object or a List of `PivotTable`

| Parameter | Data Type | Description |
|---------------|------------------------|-------------------------------------------------|
| `sheet` | str | The name of the sheet. |
| `pivot_table` | `PivotTable \| list[PivotTable]` | A single `PivotTable` object or a list of `PivotTable` objects to add to the worksheet. |

```python title='Add Pivot Table using PivotTable object'
from pyfastexcle.pivot import PivotTable, PivotTableField

pivot_table_object = PivotTableField(
data_range="Sheet1!A1:B10",
pivot_table_range="Sheet1!C3:D10",
rows=[PivotTableField()],
columns=[PivotTableField()],
data=[PivotTableField()],
row_grand_totals=True,
column_grand_totals=False,
pivot_table_style_name="PivotStyleMedium9"
)

pivot_table_object2 = PivotTableField(
data_range="Sheet1!A1:B10",
pivot_table_range="Sheet1!C3:D10",
pivot_table_style_name="PivotStyleMedium9"
)

# Add a pivot table using a PivotTable object
wb.add_pivot_table('Sheet1', pivot_table=pivot_table_object)

# Add multiple pivot tables using a list of PivotTable objects
wb.add_pivot_table('Sheet1', pivot_table=[pivot_table_object1, pivot_table_object2])
```

### Adding a Pivot Table by Specifying Ranges and Fields

| Parameter | Data Type | Description |
|------------------------|-------------------------|------------------------------------------------------------------------------|
| `sheet` | str | The name of the sheet. |
| `data_range` | `str` | The range of data to be used in the pivot table, e.g., `"Sheet1!A1:B2"`. |
| `pivot_table_range` | `str` | The range where the pivot table will be positioned, e.g., `"Sheet1!C3:D4"`. |
| `rows` | `list[PivotTableField]` | List of fields used as rows in the pivot table. |
| `pivot_filter` | `list[PivotTableField]` | List of fields used as filters in the pivot table. |
| `columns` | `list[PivotTableField]` | List of fields used as columns in the pivot table. |
| `data` | `list[PivotTableField]` | List of fields used as data fields in the pivot table. |
| `row_grand_totals` | `Optional[bool]` | Whether to display row grand totals. |
| `column_grand_totals` | `Optional[bool]` | Whether to display column grand totals. |
| `show_drill` | `Optional[bool]` | Whether to show drill indicators. |
| `show_row_headers` | `Optional[bool]` | Whether to display row headers. |
| `show_column_headers` | `Optional[bool]` | Whether to display column headers. |
| `show_row_stripes` | `Optional[bool]` | Whether to display row stripes. |
| `show_col_stripes` | `Optional[bool]` | Whether to display column stripes. |
| `show_last_column` | `Optional[bool]` | Whether to highlight the last column. |
| `use_auto_formatting` | `Optional[bool]` | Whether to use automatic formatting for the pivot table. |
| `page_over_then_down` | `Optional[bool]` | Whether to order pages from top to bottom then left to right. |
| `merge_item` | `Optional[bool]` | Whether to merge items. |
| `compact_data` | `Optional[bool]` | Whether to display data in a compact form. |
| `show_error` | `Optional[bool]` | Whether to display errors in the pivot table. |
| `pivot_table_style_name` | `Optional[str]` | The style name to apply to the pivot table. |

```python
from pyfastexcel.pivot import PivotTableField

# Add a pivot table by specifying the data range, pivot table range, and fields
wb.add_pivot_table(
'Sheet1',
data_range="Sheet1!A1:B10",
pivot_table_range="Sheet1!C3:D10",
rows=[PivotTableField()],
columns=[PivotTableField()],
data=[PivotTableField()],
row_grand_totals=True,
column_grand_totals=False,
pivot_table_style_name="PivotStyleMedium9"
)

```
84 changes: 84 additions & 0 deletions docs/worksheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,3 +689,87 @@ ws.add_chart(
legend=ChartLegendModel(position='top', show_legend_key=True),
)
```

## Add Pivot Table

This function allows you to add a pivot table to a worksheet using either a `PivotTable` object or by specifying ranges and fields directly. You can customize the appearance and functionality of the pivot table using various optional parameters.

!!! note "Note"
- You can either pass a `PivotTable` object or directly specify the data range, pivot table range, and fields.
- Ensure that the data range and pivot table range are correctly formatted and within the sheet's valid boundaries.
- Optional parameters allow you to control the visibility of row and column headers, grand totals, stripes, and more.

### Adding a Pivot Table Using a `PivotTable` Object or a List of `PivotTable`

| Parameter | Data Type | Description |
|---------------|------------------------|-------------------------------------------------|
| `pivot_table` | `PivotTable \| list[PivotTable]` | A single `PivotTable` object or a list of `PivotTable` objects to add to the worksheet. |

```python title='Add Pivot Table using PivotTable object'
from pyfastexcle.pivot import PivotTable, PivotTableField

pivot_table_object = PivotTableField(
data_range="Sheet1!A1:B10",
pivot_table_range="Sheet1!C3:D10",
rows=[PivotTableField()],
columns=[PivotTableField()],
data=[PivotTableField()],
row_grand_totals=True,
column_grand_totals=False,
pivot_table_style_name="PivotStyleMedium9"
)

pivot_table_object2 = PivotTableField(
data_range="Sheet1!A1:B10",
pivot_table_range="Sheet1!C3:D10",
pivot_table_style_name="PivotStyleMedium9"
)

# Add a pivot table using a PivotTable object
ws.add_pivot_table(pivot_table=pivot_table_object)

# Add multiple pivot tables using a list of PivotTable objects
ws.add_pivot_table(pivot_table=[pivot_table_object1, pivot_table_object2])
```

### Adding a Pivot Table by Specifying Ranges and Fields

| Parameter | Data Type | Description |
|------------------------|-------------------------|------------------------------------------------------------------------------|
| `data_range` | `str` | The range of data to be used in the pivot table, e.g., `"Sheet1!A1:B2"`. |
| `pivot_table_range` | `str` | The range where the pivot table will be positioned, e.g., `"Sheet1!C3:D4"`. |
| `rows` | `list[PivotTableField]` | List of fields used as rows in the pivot table. |
| `pivot_filter` | `list[PivotTableField]` | List of fields used as filters in the pivot table. |
| `columns` | `list[PivotTableField]` | List of fields used as columns in the pivot table. |
| `data` | `list[PivotTableField]` | List of fields used as data fields in the pivot table. |
| `row_grand_totals` | `Optional[bool]` | Whether to display row grand totals. |
| `column_grand_totals` | `Optional[bool]` | Whether to display column grand totals. |
| `show_drill` | `Optional[bool]` | Whether to show drill indicators. |
| `show_row_headers` | `Optional[bool]` | Whether to display row headers. |
| `show_column_headers` | `Optional[bool]` | Whether to display column headers. |
| `show_row_stripes` | `Optional[bool]` | Whether to display row stripes. |
| `show_col_stripes` | `Optional[bool]` | Whether to display column stripes. |
| `show_last_column` | `Optional[bool]` | Whether to highlight the last column. |
| `use_auto_formatting` | `Optional[bool]` | Whether to use automatic formatting for the pivot table. |
| `page_over_then_down` | `Optional[bool]` | Whether to order pages from top to bottom then left to right. |
| `merge_item` | `Optional[bool]` | Whether to merge items. |
| `compact_data` | `Optional[bool]` | Whether to display data in a compact form. |
| `show_error` | `Optional[bool]` | Whether to display errors in the pivot table. |
| `pivot_table_style_name` | `Optional[str]` | The style name to apply to the pivot table. |

```python
from pyfastexcel.pivot import PivotTableField

# Add a pivot table by specifying the data range, pivot table range, and fields
ws.add_pivot_table(
data_range="Sheet1!A1:B10",
pivot_table_range="Sheet1!C3:D10",
rows=[PivotTableField()],
columns=[PivotTableField()],
data=[PivotTableField()],
row_grand_totals=True,
column_grand_totals=False,
pivot_table_style_name="PivotStyleMedium9"
)

```
3 changes: 2 additions & 1 deletion pyfastexcel.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ func testExport(t *testing.T) {
"Comment": [],
"NoStyle": "false",
"Table": [],
"Chart": []
"Chart": [],
"PivotTable": []
}
}
}`
Expand Down
77 changes: 77 additions & 0 deletions pyfastexcel/core/pivot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package core

import (
"fmt"

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

func getPivotTableField(field interface{}) []excelize.PivotTableField {

var pivotTableFields []excelize.PivotTableField

fieldMappings := []fieldMapping{
{Name: "Compact", Type: "bool"},
{Name: "Data", Type: "string"},
{Name: "Name", Type: "string"},
{Name: "Outline", Type: "bool"},
{Name: "Subtotal", Type: "string"},
{Name: "DefaultSubtotal", Type: "bool"},
}

for _, f := range field.([]interface{}) {
pivotTableField := excelize.PivotTableField{}
setField(&pivotTableField, f.(map[string]interface{}), fieldMappings)
pivotTableFields = append(pivotTableFields, pivotTableField)
}
return pivotTableFields
}

func createPivotTable(file *excelize.File, pivot_data []interface{}) {
for _, pivot := range pivot_data {
pivotMap := pivot.(map[string]interface{})

rowGrandTotals := false
if pivotMap["RowGrandTotals"] != nil {
rowGrandTotals = pivotMap["RowGrandTotals"].(bool)
}
colGrandTotals := false
if pivotMap["ColGrandTotals"] != nil {
colGrandTotals = pivotMap["ColGrandTotals"].(bool)
}
showDrill := false
if pivotMap["ShowDrill"] != nil {
showDrill = pivotMap["ShowDrill"].(bool)
}
showRowHeaders := false
if pivotMap["ShowRowHeaders"] != nil {
showRowHeaders = pivotMap["ShowRowHeaders"].(bool)
}
showColHeaders := false
if pivotMap["ShowColHeaders"] != nil {
showColHeaders = pivotMap["ShowColHeaders"].(bool)
}
showLastColumn := false
if pivotMap["ShowLastColumn"] != nil {
showLastColumn = pivotMap["ShowLastColumn"].(bool)
}

err := file.AddPivotTable(&excelize.PivotTableOptions{
DataRange: pivotMap["DataRange"].(string),
PivotTableRange: pivotMap["PivotTableRange"].(string),
Rows: getPivotTableField(pivotMap["Rows"]),
Filter: getPivotTableField(pivotMap["Filter"]),
Columns: getPivotTableField(pivotMap["Columns"]),
Data: getPivotTableField(pivotMap["Data"]),
RowGrandTotals: rowGrandTotals,
ColGrandTotals: colGrandTotals,
ShowDrill: showDrill,
ShowRowHeaders: showRowHeaders,
ShowColHeaders: showColHeaders,
ShowLastColumn: showLastColumn,
})
if err != nil {
fmt.Println(err)
}
}
}
85 changes: 85 additions & 0 deletions pyfastexcel/core/pivot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package core

import (
"testing"

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

func TestGetPivotTableField(t *testing.T) {
fieldData := []interface{}{
map[string]interface{}{
"Compact": true,
"Data": "SampleData",
"Name": "SampleName",
"Outline": true,
"Subtotal": "SampleSubtotal",
"DefaultSubtotal": false,
},
}

expected := []excelize.PivotTableField{
{
Compact: true,
Data: "SampleData",
Name: "SampleName",
Outline: true,
Subtotal: "SampleSubtotal",
DefaultSubtotal: false,
},
}

result := getPivotTableField(fieldData)

if len(result) != len(expected) {
t.Errorf("Expected length %d, but got %d", len(expected), len(result))
}

for i := range expected {
if result[i] != expected[i] {
t.Errorf("Expected %+v, but got %+v", expected[i], result[i])
}
}
}

func TestCreatePivotTable(t *testing.T) {
// Initialize an excel file
file := excelize.NewFile()

// Mock pivot table data
pivotData := []interface{}{
map[string]interface{}{
"DataRange": "Sheet1!A1:D10",
"PivotTableRange": "Sheet1!F1:G10",
"Rows": []interface{}{
map[string]interface{}{
"Name": "RowField",
},
},
"Filter": []interface{}{
map[string]interface{}{
"Name": "FilterField",
},
},
"Columns": []interface{}{
map[string]interface{}{
"Name": "ColumnField",
},
},
"Data": []interface{}{
map[string]interface{}{
"Name": "DataField",
},
},
"RowGrandTotals": true,
"ColGrandTotals": true,
"ShowDrill": false,
"ShowRowHeaders": true,
"ShowColHeaders": true,
"ShowLastColumn": false,
},
}

// Call the function to test
createPivotTable(file, pivotData)
}
Loading

0 comments on commit c9af95a

Please sign in to comment.