From 030ae2484e6b76ab260d09e1153e7c4718bc655e Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 5 Dec 2024 07:20:40 +0800 Subject: [PATCH] Add 5 new functions: add_chart_sheet, add_comment, add_pivot_table, get_active_sheet_index and get_app_props - Update unit tests and docs for the function --- excelize.py | 169 ++++++++++++++++- main.go | 111 ++++++++++++ test_excelize.py | 232 +++++++++++++++++++----- types_c.h | 464 +++++++++++++++++++++++++++++------------------ types_go.py | 79 ++++++++ types_py.py | 63 +++++++ 6 files changed, 890 insertions(+), 228 deletions(-) diff --git a/excelize.py b/excelize.py index 731cc00..71867bb 100644 --- a/excelize.py +++ b/excelize.py @@ -73,7 +73,7 @@ def load_lib(): lib = CDLL(os.path.join(os.path.dirname(__file__), load_lib())) ENCODE = "utf-8" __version__ = "0.0.2" -uppercase_words = ["xml"] +uppercase_words = ["id", "xml"] def py_to_base_ctype(py_value, c_type): @@ -495,6 +495,57 @@ def add_chart( ).decode(ENCODE) return None if err == "" else Exception(err) + def add_chart_sheet( + self, sheet: str, chart: Chart, **combo: Chart + ) -> Exception | None: + """ + Create a chartsheet by given chart format set (such as offset, scale, + aspect ratio setting and print settings) and properties set. In Excel a + chartsheet is a worksheet that only contains a chart. + + Args: + sheet (str): The worksheet name + chart (Chart): Chart options + **combo (Chart): Optional parameters for combo chart + + Returns: + Exception | None: Returns None if no error occurred, + otherwise returns an Exception with the message. + """ + lib.AddChartSheet.restype = c_char_p + opts = [chart] + list(combo.values()) + charts = (types_go._Chart * len(opts))() + for i, opt in enumerate(opts): + charts[i] = py_value_to_c(opt, types_go._Chart()) + err = lib.AddChartSheet( + self.file_index, + sheet.encode(ENCODE), + byref(charts), + len(charts), + ).decode(ENCODE) + return None if err == "" else Exception(err) + + def add_comment(self, sheet: str, opts: Comment) -> Exception | None: + """ + Add comments in a sheet by giving the worksheet name, cell reference, + and format set (such as author and text). Note that the maximum author + name length is 255 and the max text length is 32512. + + Args: + sheet (str): The worksheet name + opts (Comment): The comment options + + Returns: + Exception | None: Returns None if no error occurred, + otherwise returns an Exception with the message. + """ + lib.AddComment.restype = c_char_p + options = py_value_to_c(opts, types_go._Comment()) + err = lib.AddComment( + self.file_index, sheet.encode(ENCODE), byref(options) + ).decode(ENCODE) + return None if err == "" else Exception(err) + def add_picture( self, sheet: str, cell: str, name: str, opts: GraphicOptions | None ) -> Exception | None: @@ -529,6 +580,94 @@ def add_picture( ).decode(ENCODE) return None if err == "" else Exception(err) + def add_pivot_table(self, opts: PivotTableOptions | None) -> Exception | None: + """ + Add pivot table by given pivot table options. Note that the same fields + can not in Columns, Rows and Filter fields at the same time. + + Args: + opts (PivotTableOptions): The pivot table options + + Returns: + Exception | None: Returns None if no error occurred, + otherwise returns an Exception with the message. + + Example: + For example, create a pivot table on the range reference + Sheet1!G2:M34 with the range reference Sheet1!A1:E31 as the data + source, summarize by sum for sales: + + .. code-block:: python + + import excelize + import random + + f = excelize.new_file() + month = [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + ] + year = [2017, 2018, 2019] + types = ["Meat", "Dairy", "Beverages", "Produce"] + region = ["East", "West", "North", "South"] + err = f.set_sheet_row("Sheet1", "A1", ["Month", "Year", "Type", "Sales", "Region"]) + if err: + print(err) + for row in range(2, 32): + err = f.set_cell_value("Sheet1", f"A{row}", month[random.randrange(12)]) + if err: + print(err) + err = f.set_cell_value("Sheet1", f"B{row}", year[random.randrange(3)]) + if err: + print(err) + err = f.set_cell_value("Sheet1", f"C{row}", types[random.randrange(4)]) + if err: + print(err) + err = f.set_cell_value("Sheet1", f"D{row}", random.randrange(5000)) + if err: + print(err) + err = f.set_cell_value("Sheet1", f"E{row}", region[random.randrange(4)]) + if err: + print(err) + + err = f.add_pivot_table( + excelize.PivotTableOptions( + data_range="Sheet1!A1:E31", + pivot_table_range="Sheet1!G2:M34", + rows=[ + excelize.PivotTableField(data="Month", default_subtotal=True), + excelize.PivotTableField(data="Year"), + ], + filter=[excelize.PivotTableField(data="Region")], + columns=[ + excelize.PivotTableField(data="Type", default_subtotal=True), + ], + data=[ + excelize.PivotTableField(data="Sales", name="Summarize", subtotal="Sum"), + ], + row_grand_totals=True, + col_grand_totals=True, + show_drill=True, + show_row_headers=True, + show_col_headers=True, + show_last_column=True, + ) + ) + if err: + print(err) + err = f.save_as("TestAddPivotTable.xlsx") + if err: + print(err) + err = f.close() + if err: + print(err) + """ + lib.AddPivotTable.restype = c_char_p + err = lib.AddPivotTable( + self.file_index, byref(py_value_to_c(opts, types_go._PivotTableOptions())) + ).decode(ENCODE) + return None if err == "" else Exception(err) + def close(self) -> Exception | None: """ Closes and cleanup the open temporary file for the spreadsheet. @@ -693,6 +832,34 @@ def duplicate_row_to(self, sheet: str, row: int, row2: int) -> Exception | None: ).decode(ENCODE) return None if err == "" else Exception(err) + def get_active_sheet_index(self) -> int: + """ + Get active sheet index of the spreadsheet. If not found the active sheet + will be return integer 0. + + Returns: + int: The active sheet index + """ + lib.GetActiveSheetIndex.restype = c_int + res = lib.GetActiveSheetIndex(self.file_index) + return res + + def get_app_props(self) -> Tuple[AppProperties | None, Exception | None]: + """ + Get document application properties. + + Returns: + Tuple[AppProperties | None, Exception | None]: A tuple containing the + app properties if found, otherwise None, and an Exception object if + an error occurred, otherwise None. + """ + lib.GetAppProps.restype = types_go._GetAppPropsResult + res = lib.GetAppProps(self.file_index) + err = res.err.decode(ENCODE) + return c_value_to_py(res.opts, AppProperties()) if err == "" else None, ( + None if err == "" else Exception(err) + ) + def get_cell_value( self, sheet: str, cell: str, *opts: Options ) -> Tuple[str, Exception | None]: diff --git a/main.go b/main.go index 2de6a64..efc081a 100644 --- a/main.go +++ b/main.go @@ -161,6 +161,10 @@ func cToGoArray(cArray reflect.Value, cArrayLen int) reflect.Value { val := cArray.Interface().(*C.struct_ChartSeries) arr := unsafe.Slice(val, cArrayLen) return reflect.ValueOf(arr) + case "main._Ctype_struct_PivotTableField": + val := cArray.Interface().(*C.struct_PivotTableField) + arr := unsafe.Slice(val, cArrayLen) + return reflect.ValueOf(arr) case "main._Ctype_struct_RichTextRun": val := cArray.Interface().(*C.struct_RichTextRun) arr := unsafe.Slice(val, cArrayLen) @@ -447,6 +451,61 @@ func AddChart(idx int, sheet, cell *C.char, chart *C.struct_Chart, length int) * return C.CString(errNil) } +// AddChartSheet provides the method to create a chartsheet by given chart +// format set (such as offset, scale, aspect ratio setting and print settings) +// and properties set. In Excel a chartsheet is a worksheet that only contains +// a chart. +// +//export AddChartSheet +func AddChartSheet(idx int, sheet *C.char, chart *C.struct_Chart, length int) *C.char { + f, ok := files.Load(idx) + if !ok { + return C.CString(errFilePtr) + } + charts := make([]*excelize.Chart, length) + for i, c := range unsafe.Slice(chart, length) { + goVal, err := cValueToGo(reflect.ValueOf(c), reflect.TypeOf(excelize.Chart{})) + if err != nil { + return C.CString(err.Error()) + } + c := goVal.Elem().Interface().(excelize.Chart) + charts[i] = &c + } + if len(charts) > 1 { + if err := f.(*excelize.File).AddChartSheet(C.GoString(sheet), charts[0], charts[1:]...); err != nil { + return C.CString(err.Error()) + } + return C.CString(errNil) + } + if err := f.(*excelize.File).AddChartSheet(C.GoString(sheet), charts[0]); err != nil { + return C.CString(err.Error()) + } + return C.CString(errNil) +} + +// AddComment provides the method to add comments in a sheet by giving the +// worksheet name, cell reference, and format set (such as author and text). +// Note that the maximum author name length is 255 and the max text length is +// 32512. +// +//export AddComment +func AddComment(idx int, sheet *C.char, opts *C.struct_Comment) *C.char { + var comment excelize.Comment + goVal, err := cValueToGo(reflect.ValueOf(*opts), reflect.TypeOf(excelize.Comment{})) + if err != nil { + return C.CString(err.Error()) + } + comment = goVal.Elem().Interface().(excelize.Comment) + f, ok := files.Load(idx) + if !ok { + return C.CString(errFilePtr) + } + if err := f.(*excelize.File).AddComment(C.GoString(sheet), comment); err != nil { + return C.CString(err.Error()) + } + return C.CString(errNil) +} + // Add picture in a sheet by given picture format set (such as offset, scale, // aspect ratio setting and print settings) and file path, supported image // types: BMP, EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ. @@ -474,6 +533,27 @@ func AddPicture(idx int, sheet, cell, name *C.char, opts *C.struct_GraphicOption return C.CString(errNil) } +// AddPivotTable provides the method to add pivot table by given pivot table +// options. Note that the same fields can not in Columns, Rows and Filter +// fields at the same time. +// +//export AddPivotTable +func AddPivotTable(idx int, opts *C.struct_PivotTableOptions) *C.char { + f, ok := files.Load(idx) + if !ok { + return C.CString(errFilePtr) + } + goVal, err := cValueToGo(reflect.ValueOf(*opts), reflect.TypeOf(excelize.PivotTableOptions{})) + if err != nil { + return C.CString(err.Error()) + } + options := goVal.Elem().Interface().(excelize.PivotTableOptions) + if err := f.(*excelize.File).AddPivotTable(&options); err != nil { + return C.CString(err.Error()) + } + return C.CString(errNil) +} + // CellNameToCoordinates converts alphanumeric cell name to [X, Y] coordinates // or returns an error. // @@ -669,6 +749,37 @@ func DuplicateRowTo(idx int, sheet *C.char, row, row2 int) *C.char { return C.CString(errNil) } +// GetActiveSheetIndex provides a function to get active sheet index of the +// spreadsheet. If not found the active sheet will be return integer 0. +// +//export GetActiveSheetIndex +func GetActiveSheetIndex(idx int) int { + f, ok := files.Load(idx) + if !ok { + return 0 + } + return f.(*excelize.File).GetActiveSheetIndex() +} + +// GetAppProps provides a function to get document application properties. +// +//export GetAppProps +func GetAppProps(idx int) C.struct_GetAppPropsResult { + f, ok := files.Load(idx) + if !ok { + return C.struct_GetAppPropsResult{err: C.CString(errFilePtr)} + } + opts, err := f.(*excelize.File).GetAppProps() + if err != nil { + return C.struct_GetAppPropsResult{err: C.CString(err.Error())} + } + cVal, err := goValueToC(reflect.ValueOf(*opts), reflect.ValueOf(&C.struct_AppProperties{})) + if err != nil { + return C.struct_GetAppPropsResult{err: C.CString(err.Error())} + } + return C.struct_GetAppPropsResult{opts: cVal.Elem().Interface().(C.struct_AppProperties), err: C.CString(errNil)} +} + // GetCellValue provides a function to get formatted value from cell by given // worksheet name and cell reference in spreadsheet. The return value is // converted to the `string` data type. If the cell format can be applied to diff --git a/test_excelize.py b/test_excelize.py index c22d2c8..3a6704a 100644 --- a/test_excelize.py +++ b/test_excelize.py @@ -14,6 +14,7 @@ from dataclasses import dataclass from unittest.mock import patch import datetime +import random from typing import Optional from ctypes import ( c_int, @@ -60,6 +61,12 @@ def test_open_file(self): self.assertIsNone(f) self.assertTrue(err.__str__().startswith("open Book1.xlsx")) + def test_app_props(self): + f = excelize.new_file() + props, err = f.get_app_props() + self.assertEqual(props.application, "Go Excelize") + self.assertIsNone(err) + def test_style(self): f = excelize.new_file() s = excelize.Style( @@ -166,6 +173,7 @@ def test_style(self): self.assertEqual(idx, 1) self.assertIsNone(err) self.assertIsNone(f.set_active_sheet(idx)) + self.assertEqual(f.get_active_sheet_index(), idx) idx, err = f.new_sheet(":\\/?*[]Maximum 31 characters allowed in sheet title.") self.assertEqual(idx, -1) @@ -242,58 +250,184 @@ def test_add_chart(self): cell, err = excelize.coordinates_to_cell_name(1, idx + 1, False) self.assertIsNone(err) self.assertIsNone(f.set_sheet_row("Sheet1", cell, row)) + self.assertIsNone( + f.add_chart( + "Sheet1", + "E1", + chart=excelize.Chart( + type=excelize.ChartType.Col, + series=[ + excelize.ChartSeries( + name="Sheet1!$A$2", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$2:$D$2", + ), + excelize.ChartSeries( + name="Sheet1!$A$3", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$3:$D$3", + ), + excelize.ChartSeries( + 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", + ) + ], + ), + combo=excelize.Chart( + type=excelize.ChartType.Line, + series=[ + excelize.ChartSeries( + name="Sheet1!$A$2", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$2:$D$2", + ), + excelize.ChartSeries( + name="Sheet1!$A$3", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$3:$D$3", + ), + excelize.ChartSeries( + name="Sheet1!$A$4", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$4:$D$4", + ), + ], + ), + ) + ) + self.assertIsNone( + f.add_chart_sheet( + "Sheet2", + chart=excelize.Chart( + type=excelize.ChartType.Col, + series=[ + excelize.ChartSeries( + name="Sheet1!$A$2", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$2:$D$2", + ), + excelize.ChartSeries( + name="Sheet1!$A$3", + categories="Sheet1!$B$1:$D$1", + values="Sheet1!$B$3:$D$3", + ), + excelize.ChartSeries( + 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", + ) + ], + ), + ) + ) + self.assertIsNone(f.save_as("TestAddChart.xlsx")) + self.assertIsNone(f.close()) + + def test_comment(self): + f = excelize.new_file() + self.assertIsNone( + f.add_comment( + "Sheet1", + excelize.Comment( + cell="A5", + author="Excelize", + paragraph=[ + excelize.RichTextRun( + text="Excelize: ", + font=excelize.Font(bold=True), + ), + excelize.RichTextRun( + text="This is a comment.", + ), + ], + height=40, + width=180, + ), + ) + ) + self.assertIsNone(f.save_as("TestComment.xlsx")) + self.assertIsNone(f.close()) + + def test_pivot_table(self): + f = excelize.new_file() + month = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ] + year = [2017, 2018, 2019] + types = ["Meat", "Dairy", "Beverages", "Produce"] + region = ["East", "West", "North", "South"] + self.assertIsNone( + f.set_sheet_row( + "Sheet1", "A1", ["Month", "Year", "Type", "Sales", "Region"] + ) + ) + for row in range(2, 32): + self.assertIsNone( + f.set_cell_value("Sheet1", f"A{row}", month[random.randrange(12)]) + ) + self.assertIsNone( + f.set_cell_value("Sheet1", f"B{row}", year[random.randrange(3)]) + ) + self.assertIsNone( + f.set_cell_value("Sheet1", f"C{row}", types[random.randrange(4)]) + ) + self.assertIsNone( + f.set_cell_value("Sheet1", f"D{row}", random.randrange(5000)) + ) self.assertIsNone( - f.add_chart( - "Sheet1", - "E1", - chart=excelize.Chart( - type=excelize.ChartType.Col, - series=[ - excelize.ChartSeries( - name="Sheet1!$A$2", - categories="Sheet1!$B$1:$D$1", - values="Sheet1!$B$2:$D$2", - ), - excelize.ChartSeries( - name="Sheet1!$A$3", - categories="Sheet1!$B$1:$D$1", - values="Sheet1!$B$3:$D$3", - ), - excelize.ChartSeries( - 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", - ) - ], - ), - combo=excelize.Chart( - type=excelize.ChartType.Line, - series=[ - excelize.ChartSeries( - name="Sheet1!$A$2", - categories="Sheet1!$B$1:$D$1", - values="Sheet1!$B$2:$D$2", - ), - excelize.ChartSeries( - name="Sheet1!$A$3", - categories="Sheet1!$B$1:$D$1", - values="Sheet1!$B$3:$D$3", - ), - excelize.ChartSeries( - name="Sheet1!$A$4", - categories="Sheet1!$B$1:$D$1", - values="Sheet1!$B$4:$D$4", - ), - ], - ), + f.set_cell_value("Sheet1", f"E{row}", region[random.randrange(4)]) + ) + self.assertIsNone( + f.add_pivot_table( + excelize.PivotTableOptions( + data_range="Sheet1!A1:E31", + pivot_table_range="Sheet1!G2:M34", + rows=[ + excelize.PivotTableField(data="Month", default_subtotal=True), + excelize.PivotTableField(data="Year"), + ], + filter=[excelize.PivotTableField(data="Region")], + columns=[ + excelize.PivotTableField(data="Type", default_subtotal=True), + ], + data=[ + excelize.PivotTableField( + data="Sales", name="Summarize", subtotal="Sum" + ), + ], + row_grand_totals=True, + col_grand_totals=True, + show_drill=True, + show_row_headers=True, + show_col_headers=True, + show_last_column=True, ) ) - self.assertIsNone(f.save_as("TestAddChart.xlsx")) + ) + self.assertIsNone(f.save_as("TestAddPivotTable.xlsx")) + self.assertIsNone(f.close()) def test_cell_name_to_coordinates(self): col, row, err = excelize.cell_name_to_coordinates("Z3") diff --git a/types_c.h b/types_c.h index 58f4f92..000c0a0 100644 --- a/types_c.h +++ b/types_c.h @@ -13,12 +13,13 @@ #include #include -struct Interface { - int Type; - int Integer; - char* String; - double Float64; - bool Boolean; +struct Interface +{ + int Type; + int Integer; + char *String; + double Float64; + bool Boolean; }; // Options define the options for opening and reading the spreadsheet. @@ -55,256 +56,363 @@ struct Interface { // // CultureInfo specifies the country code for applying built-in language number // format code these effect by the system's local language settings. -struct Options { - unsigned int MaxCalcIterations; - char* Password; - bool RawCellValue; - long int UnzipSizeLimit; - long int UnzipXMLSizeLimit; - char* ShortDatePattern; - char* LongDatePattern; - char* LongTimePattern; - unsigned char CultureInfo; +struct Options +{ + unsigned int MaxCalcIterations; + char *Password; + bool RawCellValue; + long int UnzipSizeLimit; + long int UnzipXMLSizeLimit; + char *ShortDatePattern; + char *LongDatePattern; + char *LongTimePattern; + unsigned char CultureInfo; +}; + +// AppProperties directly maps the document application properties. +struct AppProperties +{ + char *Application; + bool ScaleCrop; + int DocSecurity; + char *Company; + bool LinksUpToDate; + bool HyperlinksChanged; + char *AppVersion; }; // Border directly maps the border settings of the cells. -struct Border { - char* Type; - char* Color; - int Style; +struct Border +{ + char *Type; + char *Color; + int Style; }; // Fill directly maps the fill settings of the cells. -struct Fill { - char* Type; - int Pattern; - int ColorLen; - char** Color; - int Shading; +struct Fill +{ + char *Type; + int Pattern; + int ColorLen; + char **Color; + int Shading; }; // Font directly maps the font settings of the fonts. -struct Font { - bool Bold; - bool Italic; - char* Underline; - char* Family; - double Size; - bool Strike; - char* Color; - int ColorIndexed; - int* ColorTheme; - double ColorTint; - char* VertAlign; +struct Font +{ + bool Bold; + bool Italic; + char *Underline; + char *Family; + double Size; + bool Strike; + char *Color; + int ColorIndexed; + int *ColorTheme; + double ColorTint; + char *VertAlign; }; // Alignment directly maps the alignment settings of the cells. -struct Alignment { - char* Horizontal; - int Indent; - bool JustifyLastLine; - unsigned int ReadingOrder; - int RelativeIndent; - bool ShrinkToFit; - int TextRotation; - char* Vertical; - bool WrapText; +struct Alignment +{ + char *Horizontal; + int Indent; + bool JustifyLastLine; + unsigned int ReadingOrder; + int RelativeIndent; + bool ShrinkToFit; + int TextRotation; + char *Vertical; + bool WrapText; }; // Protection directly maps the protection settings of the cells. -struct Protection { - bool Hidden; - bool Locked; +struct Protection +{ + bool Hidden; + bool Locked; }; // Style directly maps the style settings of the cells. -struct Style { +struct Style +{ int BorderLen; struct Border *Border; - struct Fill Fill; - struct Font *Font; - struct Alignment *Alignment; - struct Protection *Protection; - int NumFmt; - int* DecimalPlaces; - char** CustomNumFmt; - bool NegRed; + struct Fill Fill; + struct Font *Font; + struct Alignment *Alignment; + struct Protection *Protection; + int NumFmt; + int *DecimalPlaces; + char **CustomNumFmt; + bool NegRed; }; // GraphicOptions directly maps the format settings of the picture. -struct GraphicOptions { - char* AltText; - bool* PrintObject; - bool* Locked; - bool LockAspectRatio; - bool AutoFit; - bool AutoFitIgnoreAspect; - int OffsetX; - int OffsetY; - double ScaleX; - double ScaleY; - char* Hyperlink; - char* HyperlinkType; - char* Positioning; +struct GraphicOptions +{ + char *AltText; + bool *PrintObject; + bool *Locked; + bool LockAspectRatio; + bool AutoFit; + bool AutoFitIgnoreAspect; + int OffsetX; + int OffsetY; + double ScaleX; + double ScaleY; + char *Hyperlink; + char *HyperlinkType; + char *Positioning; }; // RichTextRun directly maps the settings of the rich text run. -struct RichTextRun { - struct Font *Font; - char* Text; +struct RichTextRun +{ + struct Font *Font; + char *Text; +}; + +// Comment directly maps the comment information. +struct Comment +{ + char *Author; + int AuthorID; + char *Cell; + char *Text; + unsigned int Width; + unsigned int Height; + int ParagraphLen; + struct RichTextRun *Paragraph; }; // ChartNumFmt directly maps the number format settings of the chart. -struct ChartNumFmt { - char* CustomNumFmt; - bool SourceLinked; +struct ChartNumFmt +{ + char *CustomNumFmt; + bool SourceLinked; }; // ChartAxis directly maps the format settings of the chart axis. -struct ChartAxis { - bool None; - bool MajorGridLines; - bool MinorGridLines; - double MajorUnit; - unsigned char TickLabelPosition; - int TickLabelSkip; - bool ReverseOrder; - bool Secondary; - double* Maximum; - double* Minimum; - struct Alignment Alignment; - struct Font Font; - double LogBase; - struct ChartNumFmt NumFmt; - int TitleLen; - struct RichTextRun *Title; +struct ChartAxis +{ + bool None; + bool MajorGridLines; + bool MinorGridLines; + double MajorUnit; + unsigned char TickLabelPosition; + int TickLabelSkip; + bool ReverseOrder; + bool Secondary; + double *Maximum; + double *Minimum; + struct Alignment Alignment; + struct Font Font; + double LogBase; + struct ChartNumFmt NumFmt; + int TitleLen; + struct RichTextRun *Title; }; // ChartDimension directly maps the dimension of the chart. -struct ChartDimension { - unsigned int Width; - unsigned int Height; +struct ChartDimension +{ + unsigned int Width; + unsigned int Height; }; // ChartPlotArea directly maps the format settings of the plot area. -struct ChartPlotArea { - int SecondPlotValues; - bool ShowBubbleSize; - bool ShowCatName; - bool ShowLeaderLines; - bool ShowPercent; - bool ShowSerName; - bool ShowVal; - struct Fill Fill; - struct ChartNumFmt NumFmt; +struct ChartPlotArea +{ + int SecondPlotValues; + bool ShowBubbleSize; + bool ShowCatName; + bool ShowLeaderLines; + bool ShowPercent; + bool ShowSerName; + bool ShowVal; + struct Fill Fill; + struct ChartNumFmt NumFmt; }; // ChartLegend directly maps the format settings of the chart legend. -struct ChartLegend { - char* Position; - bool ShowLegendKey; +struct ChartLegend +{ + char *Position; + bool ShowLegendKey; }; // ChartMarker directly maps the format settings of the chart marker. -struct ChartMarker { - struct Fill Fill; - char* Symbol; - int Size; +struct ChartMarker +{ + struct Fill Fill; + char *Symbol; + int Size; }; // ChartLine directly maps the format settings of the chart line. -struct ChartLine { - unsigned char Type; - bool Smooth; - double Width; +struct ChartLine +{ + unsigned char Type; + bool Smooth; + double Width; }; // ChartSeries directly maps the format settings of the chart series. -struct ChartSeries { - char* Name; - char* Categories; - char* Values; - char* Sizes; - struct Fill Fill; - struct ChartLine Line; - struct ChartMarker Marker; - unsigned char DataLabelPosition; +struct ChartSeries +{ + char *Name; + char *Categories; + char *Values; + char *Sizes; + struct Fill Fill; + struct ChartLine Line; + struct ChartMarker Marker; + unsigned char DataLabelPosition; }; // Chart directly maps the format settings of the chart. -struct Chart { - unsigned char Type; - int SeriesLen; - struct ChartSeries *Series; - struct GraphicOptions Format; - struct ChartDimension Dimension; - struct ChartLegend Legend; - int TitleLen; - struct RichTextRun *Title; - bool* VaryColors; - struct ChartAxis XAxis; - struct ChartAxis YAxis; - struct ChartPlotArea PlotArea; - struct Fill Fill; - struct ChartLine Border; - char* ShowBlanksAs; - int BubbleSize; - int HoleSize; -}; - -struct CellNameToCoordinatesResult { +struct Chart +{ + unsigned char Type; + int SeriesLen; + struct ChartSeries *Series; + struct GraphicOptions Format; + struct ChartDimension Dimension; + struct ChartLegend Legend; + int TitleLen; + struct RichTextRun *Title; + bool *VaryColors; + struct ChartAxis XAxis; + struct ChartAxis YAxis; + struct ChartPlotArea PlotArea; + struct Fill Fill; + struct ChartLine Border; + char *ShowBlanksAs; + int BubbleSize; + int HoleSize; +}; + +// PivotTableField directly maps the field settings of the pivot table. +struct PivotTableField +{ + bool Compact; + char *Data; + char *Name; + bool Outline; + bool ShowAll; + bool InsertBlankRow; + char *Subtotal; + bool DefaultSubtotal; + int NumFmt; +}; + +// PivotTableOptions directly maps the format settings of the pivot table. +struct PivotTableOptions +{ + char *DataRange; + char *PivotTableRange; + char *Name; + int RowsLen; + struct PivotTableField *Rows; + int ColumnsLen; + struct PivotTableField *Columns; + int DataLen; + struct PivotTableField *Data; + int FilterLen; + struct PivotTableField *Filter; + bool RowGrandTotals; + bool ColGrandTotals; + bool ShowDrill; + bool UseAutoFormatting; + bool PageOverThenDown; + bool MergeItem; + bool ClassicLayout; + bool CompactData; + bool ShowError; + bool ShowRowHeaders; + bool ShowColHeaders; + bool ShowRowStripes; + bool ShowColStripes; + bool ShowLastColumn; + bool FieldPrintTitles; + bool ItemPrintTitles; + char *PivotTableStyleName; +}; + +struct CellNameToCoordinatesResult +{ int col; int row; - char* err; + char *err; }; -struct ColumnNameToNumberResult { +struct ColumnNameToNumberResult +{ int col; - char* err; + char *err; }; -struct ColumnNumberToNameResult { - char* col; - char* err; +struct ColumnNumberToNameResult +{ + char *col; + char *err; }; -struct CoordinatesToCellNameResult { - char* cell; - char* err; +struct CoordinatesToCellNameResult +{ + char *cell; + char *err; +}; + +struct OptionsResult +{ + int idx; + char *err; }; -struct OptionsResult { - int idx; - char* err; +struct GetAppPropsResult +{ + struct AppProperties opts; + char *err; }; -struct GetCellValueResult { - char* val; - char* err; +struct GetCellValueResult +{ + char *val; + char *err; }; -struct Row { - int CellLen; - char** Cell; +struct Row +{ + int CellLen; + char **Cell; }; -struct GetRowsResult { +struct GetRowsResult +{ int RowLen; struct Row *Row; - char* err; + char *err; }; -struct NewSheetResult { +struct NewSheetResult +{ int idx; - char* err; + char *err; }; -struct NewStyleResult { +struct NewStyleResult +{ int style; - char* err; + char *err; }; -struct GetStyleResult { - struct Style style; - char* err; +struct GetStyleResult +{ + struct Style style; + char *err; }; diff --git a/types_go.py b/types_go.py index e9582bd..fab9e45 100644 --- a/types_go.py +++ b/types_go.py @@ -46,6 +46,18 @@ class _Options(Structure): ] +class _AppProperties(Structure): + _fields_ = [ + ("Application", c_char_p), + ("ScaleCrop", c_bool), + ("DocSecurity", c_int), + ("Company", c_char_p), + ("LinksUpToDate", c_bool), + ("HyperlinksChanged", c_bool), + ("AppVersion", c_char_p), + ] + + class _Border(Structure): _fields_ = [ ("Type", c_char_p), @@ -141,6 +153,19 @@ class _RichTextRun(Structure): ] +class _Comment(Structure): + _fields_ = [ + ("Author", c_char_p), + ("AuthorID", c_int), + ("Cell", c_char_p), + ("Text", c_char_p), + ("Width", c_uint), + ("Height", c_uint), + ("ParagraphLen", c_int), + ("Paragraph", POINTER(_RichTextRun)), + ] + + class _ChartNumFmt(Structure): _fields_ = [ ("CustomNumFmt", c_char_p), @@ -248,6 +273,53 @@ class _Chart(Structure): ] +class _PivotTableField(Structure): + _fields_ = [ + ("Compact", c_bool), + ("Data", c_char_p), + ("Name", c_char_p), + ("Outline", c_bool), + ("ShowAll", c_bool), + ("InsertBlankRow", c_bool), + ("Subtotal", c_char_p), + ("DefaultSubtotal", c_bool), + ("NumFmt", c_int), + ] + + +class _PivotTableOptions(Structure): + _fields_ = [ + ("DataRange", c_char_p), + ("PivotTableRange", c_char_p), + ("Name", c_char_p), + ("RowsLen", c_int), + ("Rows", POINTER(_PivotTableField)), + ("ColumnsLen", c_int), + ("Columns", POINTER(_PivotTableField)), + ("DataLen", c_int), + ("Data", POINTER(_PivotTableField)), + ("FilterLen", c_int), + ("Filter", POINTER(_PivotTableField)), + ("RowGrandTotals", c_bool), + ("ColGrandTotals", c_bool), + ("ShowDrill", c_bool), + ("UseAutoFormatting", c_bool), + ("PageOverThenDown", c_bool), + ("MergeItem", c_bool), + ("ClassicLayout", c_bool), + ("CompactData", c_bool), + ("ShowError", c_bool), + ("ShowRowHeaders", c_bool), + ("ShowColHeaders", c_bool), + ("ShowRowStripes", c_bool), + ("ShowColStripes", c_bool), + ("ShowLastColumn", c_bool), + ("FieldPrintTitles", c_bool), + ("ItemPrintTitles", c_bool), + ("PivotTableStyleName", c_char_p), + ] + + class _CellNameToCoordinatesResult(Structure): _fields_ = [ ("col", c_int), @@ -277,6 +349,13 @@ class _CoordinatesToCellNameResult(Structure): ] +class _GetAppPropsResult(Structure): + _fields_ = [ + ("opts", _AppProperties), + ("err", c_char_p), + ] + + class _GetCellValueResult(Structure): _fields_ = [ ("val", c_char_p), diff --git a/types_py.py b/types_py.py index 339aa7d..9fe6187 100644 --- a/types_py.py +++ b/types_py.py @@ -192,6 +192,17 @@ class Options: culture_info: CultureName = CultureName.CultureNameUnknown +@dataclass +class AppProperties: + application: str = "" + scale_crop: bool = False + doc_security: int = 0 + company: str = "" + links_up_to_date: bool = False + hyperlinks_changed: bool = False + app_version: str = "" + + @dataclass class Border: type: str = "" @@ -287,6 +298,17 @@ class RichTextRun: text: str = "" +@dataclass +class Comment: + author: str = "" + author_id: int = 0 + cell: str = "" + text: str = "" + width: int = 0 + height: int = 0 + paragraph: Optional[list[RichTextRun]] = None + + @dataclass class ChartNumFmt: custom_num_fmt: str = "" @@ -384,3 +406,44 @@ class Chart: show_blanks_as: str = "" bubble_size: int = 0 hole_size: int = 0 + + +@dataclass +class PivotTableField: + compact: bool = False + data: str = "" + name: str = "" + outline: bool = False + show_all: bool = False + insert_blank_row: bool = False + subtotal: str = "" + default_subtotal: bool = False + num_fmt: int = 0 + + +@dataclass +class PivotTableOptions: + data_range: str = "" + pivot_table_range: str = "" + name: str = "" + rows: Optional[list[PivotTableField]] = None + columns: Optional[list[PivotTableField]] = None + data: Optional[list[PivotTableField]] = None + filter: Optional[list[PivotTableField]] = None + row_grand_totals: bool = False + col_grand_totals: bool = False + show_drill: bool = False + use_auto_formatting: bool = False + page_over_then_down: bool = False + merge_item: bool = False + classic_layout: bool = False + compact_data: bool = False + show_error: bool = False + show_row_headers: bool = False + show_col_headers: bool = False + show_row_stripes: bool = False + show_col_stripes: bool = False + show_last_column: bool = False + field_print_titles: bool = False + item_print_titles: bool = False + pivot_table_style_name: str = ""