Skip to content

Commit

Permalink
Add 3 new functions: add_slicer, add_sparkline and add_table
Browse files Browse the repository at this point in the history
- Update unit tests and docs for the function
  • Loading branch information
xuri committed Dec 7, 2024
1 parent 97210c5 commit 15df3dc
Show file tree
Hide file tree
Showing 6 changed files with 372 additions and 0 deletions.
108 changes: 108 additions & 0 deletions excelize.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,114 @@ def add_shape(self, sheet: str, opts: Shape) -> Exception | None:
).decode(ENCODE)
return None if err == "" else Exception(err)

def add_slicer(self, sheet: str, opts: SlicerOptions) -> Exception | None:
"""
Inserts a slicer by giving the worksheet name and slicer settings.
Args:
sheet (str): The worksheet name
opts (SlicerOptions): The slicer options
Returns:
Exception | None: Returns None if no error occurred,
otherwise returns an Exception with the message.
Example:
For example, insert a slicer on the Sheet1!E1 with field Column1 for
the table named Table1:
.. code-block:: python
err = f.add_slicer(
"Sheet1",
excelize.SlicerOptions(
name="Column1",
cell="E1",
table_sheet="Sheet1",
table_name="Table1",
caption="Column1",
width=200,
height=200,
),
)
"""
lib.AddSlicer.restype = c_char_p
options = py_value_to_c(opts, types_go._SlicerOptions())
err = lib.AddSlicer(
self.file_index, sheet.encode(ENCODE), byref(options)
).decode(ENCODE)
return None if err == "" else Exception(err)

def add_sparkline(self, sheet: str, opts: SparklineOptions) -> Exception | None:
"""
add sparklines to the worksheet by given formatting options. Sparklines
are small charts that fit in a single cell and are used to show trends
in data. Sparklines are a feature of Excel 2010 and later only. You can
write them to workbook that can be read by Excel 2007, but they won't be
displayed.
Args:
sheet (str): The worksheet name
opts (SparklineOptions): The sparklines options
Returns:
Exception | None: Returns None if no error occurred,
otherwise returns an Exception with the message.
Example:
For example, add a grouped sparkline. Changes are applied to all
three:
.. code-block:: python
err = f.add_sparkline(
"Sheet1",
excelize.SparklineOptions(
location=["A1", "A2", "A3"],
range=["Sheet2!A1:J1", "Sheet2!A2:J2", "Sheet2!A3:J3"],
markers=True,
),
)
"""
lib.AddSparkline.restype = c_char_p
options = py_value_to_c(opts, types_go._SparklineOptions())
err = lib.AddSparkline(
self.file_index, sheet.encode(ENCODE), byref(options)
).decode(ENCODE)
return None if err == "" else Exception(err)

def add_table(self, sheet: str, table: Table) -> Exception | None:
"""
Add table in a worksheet by given worksheet name, range reference and
format set.
Note that the table must be at least two lines including the header. The
header cells must contain strings and must be unique, and must set the
header row data of the table before calling the AddTable function.
Multiple tables range reference that can't have an intersection.
Args:
sheet (str): The worksheet name
table (Table): The table options
Returns:
Exception | None: Returns None if no error occurred,
otherwise returns an Exception with the message.
Example:
For example, create a table of A1:D5 on Sheet1:
.. code-block:: python
err = f.add_table("Sheet1", excelize.Table(range="A1:D5"))
"""
lib.AddTable.restype = c_char_p
options = py_value_to_c(table, types_go._Table())
err = lib.AddTable(
self.file_index, sheet.encode(ENCODE), byref(options)
).decode(ENCODE)
return None if err == "" else Exception(err)

def close(self) -> Exception | None:
"""
Closes and cleanup the open temporary file for the spreadsheet.
Expand Down
66 changes: 66 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,72 @@ func AddShape(idx int, sheet *C.char, opts *C.struct_Shape) *C.char {
return C.CString(errNil)
}

// AddSlicer function inserts a slicer by giving the worksheet name and slicer
// settings.
//
//export AddSlicer
func AddSlicer(idx int, sheet *C.char, opts *C.struct_SlicerOptions) *C.char {
var options excelize.SlicerOptions
goVal, err := cValueToGo(reflect.ValueOf(*opts), reflect.TypeOf(excelize.SlicerOptions{}))
if err != nil {
return C.CString(err.Error())
}
options = goVal.Elem().Interface().(excelize.SlicerOptions)
f, ok := files.Load(idx)
if !ok {
return C.CString(errFilePtr)
}
if err := f.(*excelize.File).AddSlicer(C.GoString(sheet), &options); err != nil {
return C.CString(err.Error())
}
return C.CString(errNil)
}

// AddSparkline provides a function to add sparklines to the worksheet by
// given formatting options. Sparklines are small charts that fit in a single
// cell and are used to show trends in data. Sparklines are a feature of Excel
// 2010 and later only. You can write them to workbook that can be read by Excel
// 2007, but they won't be displayed.
//
//export AddSparkline
func AddSparkline(idx int, sheet *C.char, opts *C.struct_SparklineOptions) *C.char {
var options excelize.SparklineOptions
goVal, err := cValueToGo(reflect.ValueOf(*opts), reflect.TypeOf(excelize.SparklineOptions{}))
if err != nil {
return C.CString(err.Error())
}
options = goVal.Elem().Interface().(excelize.SparklineOptions)
f, ok := files.Load(idx)
if !ok {
return C.CString(errFilePtr)
}
if err := f.(*excelize.File).AddSparkline(C.GoString(sheet), &options); err != nil {
return C.CString(err.Error())
}
return C.CString(errNil)
}

// AddTable provides the method to add table in a worksheet by given worksheet
// name, range reference and format set.
//
//export AddTable
func AddTable(idx int, sheet *C.char, table *C.struct_Table) *C.char {
var tbl excelize.Table
goVal, err := cValueToGo(reflect.ValueOf(*table), reflect.TypeOf(excelize.Table{}))
if err != nil {
return C.CString(err.Error())
}
tbl = goVal.Elem().Interface().(excelize.Table)
f, ok := files.Load(idx)
if !ok {
return C.CString(errFilePtr)
}
if err := f.(*excelize.File).AddTable(C.GoString(sheet), &tbl); err != nil {
return C.CString(err.Error())
}
return C.CString(errNil)
}

// CellNameToCoordinates converts alphanumeric cell name to [X, Y] coordinates
// or returns an error.
//
Expand Down
41 changes: 41 additions & 0 deletions test_excelize.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,47 @@ def test_add_shape(self):
self.assertIsNone(f.save_as("TestAddShape.xlsx"))
self.assertIsNone(f.close())

def test_add_slicer(self):
f = excelize.new_file()
self.assertIsNone(
f.add_table(
"Sheet1",
excelize.Table(
name="Table1",
range="A1:D5",
),
)
)
self.assertIsNone(
f.add_slicer(
"Sheet1",
excelize.SlicerOptions(
name="Column1",
cell="E1",
table_sheet="Sheet1",
table_name="Table1",
caption="Column1",
),
)
)
self.assertIsNone(f.save_as("TestAddSlicer.xlsx"))
self.assertIsNone(f.close())

def test_add_sparkline(self):
f = excelize.new_file()
self.assertIsNone(
f.add_sparkline(
"Sheet1",
excelize.SparklineOptions(
location=["A2"],
range=["Sheet1!B1:J1"],
markers=True,
),
)
)
self.assertIsNone(f.save_as("TestAddSparkline.xlsx"))
self.assertIsNone(f.close())

def test_cell_name_to_coordinates(self):
col, row, err = excelize.cell_name_to_coordinates("Z3")
self.assertEqual(col, 26)
Expand Down
54 changes: 54 additions & 0 deletions types_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ struct Alignment
bool WrapText;
};

// AutoFilterOptions directly maps the auto filter settings.
struct AutoFilterOptions
{
char *Column;
char *Expression;
};

// Protection directly maps the protection settings of the cells.
struct Protection
{
Expand Down Expand Up @@ -403,6 +410,53 @@ struct SlicerOptions
struct GraphicOptions Format;
};

// SparklineOptions directly maps the settings of the sparkline.
struct SparklineOptions
{
int LocationLen;
char **Location;
int RangeLen;
char **Range;
int Max;
int CustMax;
int Min;
int CustMin;
char *Type;
double Weight;
bool DateAxis;
bool Markers;
bool High;
bool Low;
bool First;
bool Last;
bool Negative;
bool Axis;
bool Hidden;
bool Reverse;
int Style;
char *SeriesColor;
char *NegativeColor;
char *MarkersColor;
char *FirstColor;
char *LastColor;
char *HightColor;
char *LowColor;
char *EmptyCells;
};

// Table directly maps the format settings of the table.
struct Table
{
char *Range;
char *Name;
char *StyleName;
bool ShowColumnStripes;
bool ShowFirstColumn;
bool *ShowHeaderRow;
bool ShowLastColumn;
bool *ShowRowStripes;
};

struct CellNameToCoordinatesResult
{
int col;
Expand Down
54 changes: 54 additions & 0 deletions types_go.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ class _Protection(Structure):
]


class _AutoFilterOptions(Structure):
_fields_ = [
("Column", c_char_p),
("Expression", c_char_p),
]


class _Style(Structure):
_fields_ = [
("BorderLen", c_int),
Expand Down Expand Up @@ -380,6 +387,53 @@ class _SlicerOptions(Structure):
]


class _SparklineOptions(Structure):
_fields_ = [
("LocationLen", c_int),
("Location", POINTER(POINTER(c_char))),
("RangeLen", c_int),
("Range", POINTER(POINTER(c_char))),
("Max", c_int),
("CustMax", c_int),
("Min", c_int),
("CustMin", c_int),
("Type", c_char_p),
("Weight", c_double),
("DateAxis", c_bool),
("Markers", c_bool),
("High", c_bool),
("Low", c_bool),
("First", c_bool),
("Last", c_bool),
("Negative", c_bool),
("Axis", c_bool),
("Hidden", c_bool),
("Reverse", c_bool),
("Style", c_int),
("SeriesColor", c_char_p),
("NegativeColor", c_char_p),
("MarkersColor", c_char_p),
("FirstColor", c_char_p),
("LastColor", c_char_p),
("HightColor", c_char_p),
("LowColor", c_char_p),
("EmptyCells", c_char_p),
]


class _Table(Structure):
_fields_ = [
("Range", c_char_p),
("Name", c_char_p),
("StyleName", c_char_p),
("ShowColumnStripes", c_bool),
("ShowFirstColumn", c_bool),
("ShowHeaderRow", POINTER(c_bool)),
("ShowLastColumn", c_bool),
("ShowRowStripes", POINTER(c_bool)),
]


class _CellNameToCoordinatesResult(Structure):
_fields_ = [
("col", c_int),
Expand Down
Loading

0 comments on commit 15df3dc

Please sign in to comment.