Skip to content

Commit 41f4724

Browse files
committed
Add 2 new functions: get_page_margins and get_pivot_tables
- Update unit tests
1 parent c8126fe commit 41f4724

6 files changed

Lines changed: 201 additions & 51 deletions

File tree

excelize.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,6 +3285,45 @@ def get_page_layout(self, sheet: str) -> PageLayoutOptions:
32853285
return c_value_to_py(res.opts, PageLayoutOptions())
32863286
raise RuntimeError(err)
32873287

3288+
def get_page_margins(self, sheet: str) -> PageLayoutMarginsOptions:
3289+
"""
3290+
Get worksheet page margins.
3291+
3292+
Returns:
3293+
PageLayoutMarginsOptions: Return the worksheet page margins if no
3294+
error occurred, otherwise raise a RuntimeError with the message.
3295+
"""
3296+
prepare_args([sheet], [argsRule("sheet", [str])])
3297+
lib.GetPageMargins.restype = types_go._GetPageMarginsResult
3298+
res = lib.GetPageMargins(self.file_index, sheet.encode(ENCODE))
3299+
err = res.err.decode(ENCODE)
3300+
if not err:
3301+
return c_value_to_py(res.opts, PageLayoutMarginsOptions())
3302+
raise RuntimeError(err)
3303+
3304+
def get_pivot_tables(self, sheet: str) -> List[PivotTableOptions]:
3305+
"""
3306+
Returns all pivot table definitions in a worksheet by given worksheet
3307+
name. Currently only support get pivot table cache with worksheet source
3308+
type, and doesn't support source types: external, consolidation and
3309+
scenario.
3310+
3311+
Args:
3312+
sheet (str): The worksheet name
3313+
3314+
Returns:
3315+
List[PivotTableOptions]: Return pivot table options if no error
3316+
occurred, otherwise raise a RuntimeError with the message.
3317+
"""
3318+
prepare_args([sheet], [argsRule("sheet", [str])])
3319+
lib.GetPivotTables.restype = types_go._GetPivotTablesResult
3320+
res = lib.GetPivotTables(self.file_index, sheet.encode(ENCODE))
3321+
pivot_tables = c_value_to_py(res, GetPivotTablesResult()).pivot_tables
3322+
err = res.Err.decode(ENCODE)
3323+
if not err:
3324+
return pivot_tables if pivot_tables else []
3325+
raise RuntimeError(err)
3326+
32883327
def get_row_height(self, sheet: str, row: int) -> float:
32893328
"""
32903329
Get row height by given worksheet name and row number.

main.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,51 @@ func GetPageLayout(idx int, sheet *C.char) C.struct_GetPageLayoutResult {
14291429
return C.struct_GetPageLayoutResult{opts: cVal.Elem().Interface().(C.struct_PageLayoutOptions), err: C.CString(emptyString)}
14301430
}
14311431

1432+
// GetPageMargins provides a function to get worksheet page margins.
1433+
//
1434+
//export GetPageMargins
1435+
func GetPageMargins(idx int, sheet *C.char) C.struct_GetPageMarginsResult {
1436+
f, ok := files.Load(idx)
1437+
if !ok {
1438+
return C.struct_GetPageMarginsResult{err: C.CString(errFilePtr)}
1439+
}
1440+
opts, err := f.(*excelize.File).GetPageMargins(C.GoString(sheet))
1441+
if err != nil {
1442+
return C.struct_GetPageMarginsResult{err: C.CString(err.Error())}
1443+
}
1444+
cVal, err := goValueToC(reflect.ValueOf(opts), reflect.ValueOf(&C.struct_PageLayoutMarginsOptions{}))
1445+
if err != nil {
1446+
return C.struct_GetPageMarginsResult{err: C.CString(err.Error())}
1447+
}
1448+
return C.struct_GetPageMarginsResult{opts: cVal.Elem().Interface().(C.struct_PageLayoutMarginsOptions), err: C.CString(emptyString)}
1449+
}
1450+
1451+
// GetPivotTables returns all pivot table definitions in a worksheet by given
1452+
// worksheet name. Currently only support get pivot table cache with worksheet
1453+
// source type, and doesn't support source types: external, consolidation
1454+
// and scenario.
1455+
//
1456+
//export GetPivotTables
1457+
func GetPivotTables(idx int, sheet *C.char) C.struct_GetPivotTablesResult {
1458+
f, ok := files.Load(idx)
1459+
if !ok {
1460+
return C.struct_GetPivotTablesResult{Err: C.CString(errFilePtr)}
1461+
}
1462+
pivotTables, err := f.(*excelize.File).GetPivotTables(C.GoString(sheet))
1463+
if err != nil {
1464+
return C.struct_GetPivotTablesResult{Err: C.CString(err.Error())}
1465+
}
1466+
cArray := C.malloc(C.size_t(len(pivotTables)) * C.size_t(unsafe.Sizeof(C.struct_PivotTableOptions{})))
1467+
for i, tbl := range pivotTables {
1468+
cVal, err := goValueToC(reflect.ValueOf(tbl), reflect.ValueOf(&C.struct_PivotTableOptions{}))
1469+
if err != nil {
1470+
return C.struct_GetPivotTablesResult{Err: C.CString(err.Error())}
1471+
}
1472+
*(*C.struct_PivotTableOptions)(unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(C.struct_PivotTableOptions{}))) = cVal.Elem().Interface().(C.struct_PivotTableOptions)
1473+
}
1474+
return C.struct_GetPivotTablesResult{PivotTablesLen: C.int(len(pivotTables)), PivotTables: (*C.struct_PivotTableOptions)(cArray), Err: C.CString(emptyString)}
1475+
}
1476+
14321477
// GetRowHeight provides a function to get row height by given worksheet name
14331478
// and row number.
14341479
//

test_excelize.py

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,12 @@ def test_none_file_pointer(self):
10021002
with self.assertRaises(RuntimeError) as context:
10031003
f.get_page_layout("Sheet1")
10041004
self.assertEqual(str(context.exception), expected)
1005+
with self.assertRaises(RuntimeError) as context:
1006+
f.get_page_margins("Sheet1")
1007+
self.assertEqual(str(context.exception), expected)
1008+
with self.assertRaises(RuntimeError) as context:
1009+
f.get_pivot_tables("Sheet1")
1010+
self.assertEqual(str(context.exception), expected)
10051011
with self.assertRaises(RuntimeError) as context:
10061012
f.get_sheet_name(0)
10071013
self.assertEqual(str(context.exception), expected)
@@ -1530,16 +1536,16 @@ def test_header_footer(self):
15301536

15311537
def test_page_layout(self):
15321538
f = excelize.new_file()
1533-
opts = excelize.PageLayoutOptions(
1534-
size=1,
1535-
orientation="landscape",
1536-
first_page_number=1,
1537-
adjust_to=120,
1538-
fit_to_height=2,
1539-
fit_to_width=2,
1540-
black_and_white=True,
1541-
page_order="overThenDown",
1542-
)
1539+
opts = excelize.PageLayoutOptions(
1540+
size=1,
1541+
orientation="landscape",
1542+
first_page_number=1,
1543+
adjust_to=120,
1544+
fit_to_height=2,
1545+
fit_to_width=2,
1546+
black_and_white=True,
1547+
page_order="overThenDown",
1548+
)
15431549
self.assertIsNone(f.set_page_layout("Sheet1", opts))
15441550
with self.assertRaises(RuntimeError) as context:
15451551
f.set_page_layout("SheetN", excelize.PageLayoutOptions())
@@ -1565,21 +1571,17 @@ def test_page_layout(self):
15651571

15661572
def test_page_margins(self):
15671573
f = excelize.new_file()
1568-
self.assertIsNone(
1569-
f.set_page_margins(
1570-
"Sheet1",
1571-
excelize.PageLayoutMarginsOptions(
1572-
bottom=1.0,
1573-
footer=1.0,
1574-
header=1.0,
1575-
left=1.0,
1576-
right=1.0,
1577-
top=1.0,
1578-
horizontally=True,
1579-
vertically=True,
1580-
),
1581-
)
1582-
)
1574+
opts = excelize.PageLayoutMarginsOptions(
1575+
bottom=1.0,
1576+
footer=1.0,
1577+
header=1.0,
1578+
left=1.0,
1579+
right=1.0,
1580+
top=1.0,
1581+
horizontally=True,
1582+
vertically=True,
1583+
)
1584+
self.assertIsNone(f.set_page_margins("Sheet1", opts))
15831585
with self.assertRaises(RuntimeError) as context:
15841586
f.set_page_margins("SheetN", excelize.PageLayoutMarginsOptions())
15851587
self.assertEqual(str(context.exception), "sheet SheetN does not exist")
@@ -1589,6 +1591,16 @@ def test_page_margins(self):
15891591
str(context.exception),
15901592
"expected type PageLayoutMarginsOptions for argument 'opts', but got int",
15911593
)
1594+
self.assertEqual(f.get_page_margins("Sheet1"), opts)
1595+
with self.assertRaises(RuntimeError) as context:
1596+
f.get_page_margins("SheetN")
1597+
self.assertEqual(str(context.exception), "sheet SheetN does not exist")
1598+
with self.assertRaises(TypeError) as context:
1599+
f.get_page_margins(1)
1600+
self.assertEqual(
1601+
str(context.exception),
1602+
"expected type str for argument 'sheet', but got int",
1603+
)
15921604
self.assertIsNone(f.save_as(os.path.join("test", "TestPageMargins.xlsx")))
15931605
self.assertIsNone(f.close())
15941606

@@ -1666,32 +1678,52 @@ def test_pivot_table(self):
16661678
self.assertIsNone(
16671679
f.set_cell_value("Sheet1", f"E{row}", region[random.randrange(4)])
16681680
)
1669-
self.assertIsNone(
1670-
f.add_pivot_table(
1671-
excelize.PivotTableOptions(
1672-
data_range="Sheet1!A1:E31",
1673-
pivot_table_range="Sheet1!G2:M34",
1674-
rows=[
1675-
excelize.PivotTableField(data="Month", default_subtotal=True),
1676-
excelize.PivotTableField(data="Year"),
1677-
],
1678-
filter=[excelize.PivotTableField(data="Region")],
1679-
columns=[
1680-
excelize.PivotTableField(data="Type", default_subtotal=True),
1681-
],
1682-
data=[
1683-
excelize.PivotTableField(
1684-
data="Sales", name="Summarize", subtotal="Sum"
1685-
),
1686-
],
1687-
row_grand_totals=True,
1688-
col_grand_totals=True,
1689-
show_drill=True,
1690-
show_row_headers=True,
1691-
show_col_headers=True,
1692-
show_last_column=True,
1693-
)
1694-
)
1681+
opts = excelize.PivotTableOptions(
1682+
data_range="Sheet1!A1:E31",
1683+
pivot_table_range="Sheet1!G2:M34",
1684+
rows=[
1685+
excelize.PivotTableField(data="Month", default_subtotal=True),
1686+
excelize.PivotTableField(data="Year"),
1687+
],
1688+
filter=[excelize.PivotTableField(data="Region")],
1689+
columns=[
1690+
excelize.PivotTableField(data="Type", default_subtotal=True),
1691+
],
1692+
data=[
1693+
excelize.PivotTableField(
1694+
data="Sales", name="Summarize", subtotal="Sum"
1695+
),
1696+
],
1697+
row_grand_totals=True,
1698+
col_grand_totals=True,
1699+
show_drill=True,
1700+
show_row_headers=True,
1701+
show_col_headers=True,
1702+
show_last_column=True,
1703+
)
1704+
self.assertIsNone(f.add_pivot_table(opts))
1705+
tables = f.get_pivot_tables("Sheet1")
1706+
self.assertEqual(len(tables), 1)
1707+
self.assertEqual(tables[0].data_range, opts.data_range)
1708+
self.assertEqual(tables[0].pivot_table_range, opts.pivot_table_range)
1709+
self.assertEqual(tables[0].rows, opts.rows)
1710+
self.assertEqual(tables[0].filter, opts.filter)
1711+
self.assertEqual(tables[0].columns, opts.columns)
1712+
self.assertEqual(tables[0].data, opts.data)
1713+
self.assertEqual(tables[0].row_grand_totals, opts.row_grand_totals)
1714+
self.assertEqual(tables[0].col_grand_totals, opts.col_grand_totals)
1715+
self.assertEqual(tables[0].show_drill, opts.show_drill)
1716+
self.assertEqual(tables[0].show_row_headers, opts.show_row_headers)
1717+
self.assertEqual(tables[0].show_col_headers, opts.show_col_headers)
1718+
self.assertEqual(tables[0].show_last_column, opts.show_last_column)
1719+
with self.assertRaises(RuntimeError) as context:
1720+
f.get_pivot_tables("SheetN")
1721+
self.assertEqual(str(context.exception), "sheet SheetN does not exist")
1722+
with self.assertRaises(TypeError) as context:
1723+
f.get_pivot_tables(1)
1724+
self.assertEqual(
1725+
str(context.exception),
1726+
"expected type str for argument 'sheet', but got int",
16951727
)
16961728
with self.assertRaises(RuntimeError) as context:
16971729
f.add_pivot_table(excelize.PivotTableOptions())

types_c.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,19 @@ struct GetPageLayoutResult
942942
char *err;
943943
};
944944

945+
struct GetPageMarginsResult
946+
{
947+
struct PageLayoutMarginsOptions opts;
948+
char *err;
949+
};
950+
951+
struct GetPivotTablesResult
952+
{
953+
int PivotTablesLen;
954+
struct PivotTableOptions *PivotTables;
955+
char *Err;
956+
};
957+
945958
struct GetRowOptsResult
946959
{
947960
struct RowOpts opts;

types_go.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,21 @@ class _GetPageLayoutResult(Structure):
933933
]
934934

935935

936+
class _GetPageMarginsResult(Structure):
937+
_fields_ = [
938+
("opts", _PageLayoutMarginsOptions),
939+
("err", c_char_p),
940+
]
941+
942+
943+
class _GetPivotTablesResult(Structure):
944+
_fields_ = [
945+
("PivotTablesLen", c_int),
946+
("PivotTables", POINTER(_PivotTableOptions)),
947+
("Err", c_char_p),
948+
]
949+
950+
936951
class _GetRowOptsResult(Structure):
937952
_fields_ = [
938953
("opts", _RowOpts),

types_py.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,3 +899,9 @@ class GetSheetMapResult:
899899
class GetCommentsResult:
900900
comments: Optional[List[Comment]] = None
901901
err: str = ""
902+
903+
904+
@dataclass
905+
class GetPivotTablesResult:
906+
pivot_tables: Optional[List[PivotTableOptions]] = None
907+
err: str = ""

0 commit comments

Comments
 (0)