Skip to content

Commit

Permalink
Add 4 new stream mode functions: insert_page_break, merge_cell, set_c…
Browse files Browse the repository at this point in the history
…ol_width and set_panes

- Update unit tests and docs for the function
  • Loading branch information
xuri committed Jan 8, 2025
1 parent 4d0e021 commit 5b8eb2e
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 3 deletions.
95 changes: 93 additions & 2 deletions excelize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]


Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
71 changes: 71 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
26 changes: 25 additions & 1 deletion test_excelize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -98,7 +122,7 @@ def test_stream_writer(self):
),
)
)

self.assertIsNone(sw.flush())
self.assertIsNone(f.save_as(os.path.join("test", "TestStreamWriter.xlsx")))

Expand Down

0 comments on commit 5b8eb2e

Please sign in to comment.