diff --git a/excelize.py b/excelize.py index 126878d..860763e 100644 --- a/excelize.py +++ b/excelize.py @@ -84,7 +84,7 @@ def load_lib(): lib = CDLL(os.path.join(os.path.dirname(__file__), load_lib())) ENCODE = "utf-8" -__version__ = "0.0.2" +__version__ = "0.0.3" uppercase_words = ["id", "rgb", "sq", "xml"] @@ -474,6 +474,97 @@ def add_table(self, table: Table) -> Optional[Exception]: err = lib.StreamAddTable(self.sw_index, byref(options)).decode(ENCODE) return None if err == "" else Exception(err) + def insert_page_break(self, cell: str) -> Optional[Exception]: + """ + Creates a page break to determine where the printed page ends and where + begins the next one by a given cell reference, the content before the + page break will be printed on one page and after the page break on + another. + + Args: + cell (str): The cell reference + + Returns: + Optional[Exception]: Returns None if no error occurred, + otherwise returns an Exception with the message. + """ + lib.StreamInsertPageBreak.restype = c_char_p + err = lib.StreamInsertPageBreak(self.sw_index, cell.encode(ENCODE)).decode( + ENCODE + ) + return None if err == "" else Exception(err) + + def merge_cell( + self, top_left_cell: str, bottom_right_cell: str + ) -> Optional[Exception]: + """ + Merge cells by a given range reference for the stream writer. Don't + create a merged cell that overlaps with another existing merged cell. + + Args: + top_left_cell (str): The top-left cell reference + bottom_right_cell (str): The right-bottom cell reference + + Returns: + Optional[Exception]: Returns None if no error occurred, + otherwise returns an Exception with the message. + """ + lib.StreamMergeCell.restype = c_char_p + err = lib.StreamMergeCell( + self.sw_index, + top_left_cell.encode(ENCODE), + bottom_right_cell.encode(ENCODE), + ).decode(ENCODE) + return None if err == "" else Exception(err) + + def set_col_width( + self, start_col: int, end_col: int, width: float + ) -> Optional[Exception]: + """ + Set the width of a single column or multiple columns for the stream + writer. Note that you must call the 'set_col_width' function before the + 'set_row' function. + + Args: + start_col (int): The start column number + end_col (int): The end column number + width (float): The column width + + Returns: + Optional[Exception]: Returns None if no error occurred, + otherwise returns an Exception with the message. + + Example: + For example set the width column B:C as 20: + + .. code-block:: python + + err = sw.set_col_width(2, 3, 20) + """ + lib.StreamSetColWidth.restype = c_char_p + err = lib.StreamSetColWidth( + self.sw_index, c_int(start_col), c_int(end_col), c_double(width) + ).decode(ENCODE) + return None if err == "" else Exception(err) + + def set_panes(self, opts: Panes) -> Optional[Exception]: + """ + Create and remove freeze panes and split panes by giving panes options + for the stream writer. Note that you must call the 'set_panes' function + before the 'set_row' function. + + Args: + opts (Panes): The panes options + + Returns: + Optional[Exception]: Returns None if no error occurred, + otherwise returns an Exception with the message. + """ + lib.StreamSetPanes.restype = c_char_p + options = py_value_to_c(opts, types_go._Panes()) + err = lib.StreamSetPanes(self.sw_index, byref(options)).decode(ENCODE) + return None if err == "" else Exception(err) + def set_row( self, cell: str, @@ -2477,7 +2568,7 @@ def set_col_width( Args: sheet (str): The worksheet name start_col (str): The start column name - end_col (bool): The end column name + end_col (str): The end column name width (float): The column width Returns: diff --git a/main.go b/main.go index c98e086..226339e 100644 --- a/main.go +++ b/main.go @@ -1443,6 +1443,77 @@ func StreamAddTable(swIdx int, table *C.struct_Table) *C.char { return C.CString(emptyString) } +// StreamInsertPageBreak creates a page break to determine where the printed +// page ends and where begins the next one by a given cell reference, the +// content before the page break will be printed on one page and after the page +// break on another. +// +//export StreamInsertPageBreak +func StreamInsertPageBreak(swIDx int, cell *C.char) *C.char { + streamWriter, ok := sw.Load(swIDx) + if !ok { + return C.CString(errStreamWriterPtr) + } + if err := streamWriter.(*excelize.StreamWriter).InsertPageBreak(C.GoString(cell)); err != nil { + return C.CString(err.Error()) + } + return C.CString(emptyString) +} + +// StreamMergeCell provides a function to merge cells by a given range reference +// for the StreamWriter. Don't create a merged cell that overlaps with another +// existing merged cell. +// +//export StreamMergeCell +func StreamMergeCell(swIDx int, topLeftCell, bottomRightCell *C.char) *C.char { + streamWriter, ok := sw.Load(swIDx) + if !ok { + return C.CString(errStreamWriterPtr) + } + if err := streamWriter.(*excelize.StreamWriter).MergeCell(C.GoString(topLeftCell), C.GoString(bottomRightCell)); err != nil { + return C.CString(err.Error()) + } + return C.CString(emptyString) +} + +// StreamSetColWidth provides a function to set the width of a single column or +// multiple columns for the StreamWriter. Note that you must call +// the 'StreamSetColWidth' function before the 'StreamSetRow' function. +// +//export StreamSetColWidth +func StreamSetColWidth(swIDx int, minVal, maxVal int, width float64) *C.char { + streamWriter, ok := sw.Load(swIDx) + if !ok { + return C.CString(errStreamWriterPtr) + } + if err := streamWriter.(*excelize.StreamWriter).SetColWidth(minVal, maxVal, width); err != nil { + return C.CString(err.Error()) + } + return C.CString(emptyString) +} + +// StreamSetPanes provides a function to create and remove freeze panes and +// split panes by giving panes options for the StreamWriter. Note that you must +// call the 'StreamSetPanes' function before the 'StreamSetRow' function. +// +//export StreamSetPanes +func StreamSetPanes(swIDx int, opts *C.struct_Panes) *C.char { + var options excelize.Panes + goVal, err := cValueToGo(reflect.ValueOf(*opts), reflect.TypeOf(excelize.Panes{})) + if err != nil { + return C.CString(err.Error()) + } + streamWriter, ok := sw.Load(swIDx) + if !ok { + return C.CString(errStreamWriterPtr) + } + options = goVal.Elem().Interface().(excelize.Panes) + if err := streamWriter.(*excelize.StreamWriter).SetPanes(&options); err != nil { + return C.CString(err.Error()) + } + return C.CString(emptyString) +} + // StreamSetRow writes an array to stream rows by giving starting cell reference // and a pointer to an array of values. Note that you must call the 'StreamFlush' // function to end the streaming writing process. diff --git a/test_excelize.py b/test_excelize.py index ca2f57c..33f5ec6 100644 --- a/test_excelize.py +++ b/test_excelize.py @@ -83,6 +83,30 @@ def test_stream_writer(self): self.assertEqual(str(err), "sheet SheetN does not exist") sw, err = f.new_stream_writer("Sheet1") self.assertIsNone(err) + + self.assertIsNone(sw.insert_page_break("A1")) + self.assertIsNone(sw.merge_cell("D1", "E2")) + self.assertIsNone(sw.set_col_width(3, 2, 20)) + self.assertIsNone( + sw.set_panes( + excelize.Panes( + freeze=True, + split=False, + x_split=1, + y_split=0, + top_left_cell="B1", + active_pane="topRight", + selection=[ + excelize.Selection( + sq_ref="K16", + active_cell="K16", + pane="topRight", + ) + ], + ), + ) + ) + self.assertIsNone(sw.set_row("A1", ["Column1", "Column2", "Column3"])) for r in range(4, 11): row = [random.randrange(640000) for _ in range(1, 4)] @@ -98,7 +122,7 @@ def test_stream_writer(self): ), ) ) - + self.assertIsNone(sw.flush()) self.assertIsNone(f.save_as(os.path.join("test", "TestStreamWriter.xlsx")))