Skip to content

Commit 035a0f8

Browse files
authored
Add 3 new functions: get_comments, get_sheet_list and get_sheet_map (#18)
- Update unie tests
1 parent 06fc248 commit 035a0f8

File tree

8 files changed

+203
-12
lines changed

8 files changed

+203
-12
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ finally:
8989

9090
With Excelize chart generation and management is as easy as a few lines of code. You can build charts based on data in your worksheet or generate charts without any data in your worksheet at all.
9191

92-
<p align="center"><img width="650" src="./chart.png" alt="Excelize"></p>
92+
<p align="center"><img width="650" src="https://github.com/xuri/excelize-py/raw/main/chart.png" alt="Excelize"></p>
9393

9494
```python
9595
import excelize

README_zh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ finally:
8989

9090
使用 Excelize 生成图表十分简单,仅需几行代码。您可以根据工作表中的已有数据构建图表,或向工作表中添加数据并创建图表。
9191

92-
<p align="center"><img width="650" src="./chart.png" alt="使用 Excelize 在 Excel 电子表格文档中创建图表"></p>
92+
<p align="center"><img width="650" src="https://github.com/xuri/excelize-py/raw/main/chart.png" alt="使用 Excelize 在 Excel 电子表格文档中创建图表"></p>
9393

9494
```python
9595
import excelize

excelize.py

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from dataclasses import fields
1414
from datetime import datetime, date, time
1515
from enum import Enum
16-
from typing import Tuple, get_args, get_origin, List, Optional, Union
16+
from typing import Tuple, get_args, get_origin, Dict, List, Optional, Union
1717
from ctypes import (
1818
byref,
1919
c_bool,
@@ -1692,14 +1692,30 @@ def get_col_width(self, sheet: str, col: str) -> float:
16921692
```
16931693
"""
16941694
lib.GetColWidth.restype = types_go._Float64ErrorResult
1695-
res = lib.GetColWidth(
1696-
self.file_index, sheet.encode(ENCODE), col.encode(ENCODE)
1697-
)
1695+
res = lib.GetColWidth(self.file_index, sheet.encode(ENCODE), col.encode(ENCODE))
16981696
err = res.err.decode(ENCODE)
16991697
if not err:
17001698
return res.val
17011699
raise RuntimeError(err)
17021700

1701+
def get_comments(self, sheet: str) -> List[Comment]:
1702+
"""
1703+
GetComments retrieves all comments in a worksheet by given worksheet
1704+
name.
1705+
1706+
Returns:
1707+
List[Comment]: Return the comment list if no error occurred,
1708+
otherwise raise a RuntimeError with the message.
1709+
"""
1710+
lib.GetComments.restype = types_go._GetCommentsResult
1711+
res = lib.GetComments(self.file_index, sheet.encode(ENCODE))
1712+
result = c_value_to_py(res, GetCommentsResult())
1713+
if res.Err:
1714+
err = res.Err.decode(ENCODE)
1715+
if err:
1716+
raise RuntimeError(err)
1717+
return result.comments if result and result.comments else []
1718+
17031719
def get_default_font(self) -> str:
17041720
"""
17051721
Get the default font name currently set in the workbook. The spreadsheet
@@ -1827,6 +1843,38 @@ def get_sheet_index(self, sheet: str) -> int:
18271843
return res.val
18281844
raise RuntimeError(err)
18291845

1846+
def get_sheet_list(self) -> List[str]:
1847+
"""
1848+
GetSheetList provides a function to get worksheets, chart sheets, and
1849+
dialog sheets name list of the workbook.
1850+
1851+
Returns:
1852+
List[str]: Return the sheet name list if no error occurred,
1853+
otherwise return an empty list.
1854+
"""
1855+
lib.GetSheetList.restype = types_go._StringArrayErrorResult
1856+
res = lib.GetSheetList(self.file_index)
1857+
arr = c_value_to_py(res, StringArrayErrorResult()).arr
1858+
return arr if arr else []
1859+
1860+
def get_sheet_map(self) -> Dict[int, str]:
1861+
"""
1862+
GetSheetMap provides a function to get worksheets, chart sheets, dialog
1863+
sheets ID, and name maps of the workbook.
1864+
1865+
Returns:
1866+
dict[int, str]: Return the sheet ID and name map if no error
1867+
occurred, otherwise return an empty dictionary.
1868+
"""
1869+
lib.GetSheetMap.restype = types_go._GetSheetMapResult
1870+
sheet_map = dict()
1871+
res = lib.GetSheetMap(self.file_index)
1872+
result = c_value_to_py(res, GetSheetMapResult()).arr
1873+
if result:
1874+
for item in result:
1875+
sheet_map[item.k] = item.v
1876+
return sheet_map
1877+
18301878
def get_sheet_name(self, sheet: int) -> str:
18311879
"""
18321880
Get the sheet name of the workbook by the given sheet index.
@@ -3744,9 +3792,7 @@ def open_file(filename: str, *opts: Options) -> File:
37443792
raise RuntimeError(err)
37453793

37463794

3747-
def open_reader(
3748-
buffer: bytes, *opts: Options
3749-
) -> Optional[File]:
3795+
def open_reader(buffer: bytes, *opts: Options) -> Optional[File]:
37503796
"""
37513797
Read data stream from bytes and return a populated spreadsheet file.
37523798

main.go

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,10 @@ func AddFormControl(idx int, sheet *C.char, opts *C.struct_FormControl) *C.char
548548
return C.CString(emptyString)
549549
}
550550

551-
// Add picture in a sheet by given picture format set (such as offset, scale,
552-
// aspect ratio setting and print settings) and file path, supported image
553-
// types: BMP, EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF, WMF, and WMZ.
551+
// AddPicture add picture in a sheet by given picture format set (such as
552+
// offset, scale, aspect ratio setting and print settings) and file path,
553+
// supported image types: BMP, EMF, EMZ, GIF, JPEG, JPG, PNG, SVG, TIF, TIFF,
554+
// WMF, and WMZ.
554555
//
555556
//export AddPicture
556557
func AddPicture(idx int, sheet, cell, name *C.char, opts *C.struct_GraphicOptions) *C.char {
@@ -1189,6 +1190,29 @@ func GetColWidth(idx int, sheet, col *C.char) C.struct_Float64ErrorResult {
11891190
return C.struct_Float64ErrorResult{val: C.double(val), err: C.CString(emptyString)}
11901191
}
11911192

1193+
// GetComments retrieves all comments in a worksheet by given worksheet name.
1194+
//
1195+
//export GetComments
1196+
func GetComments(idx int, sheet *C.char) C.struct_GetCommentsResult {
1197+
f, ok := files.Load(idx)
1198+
if !ok {
1199+
return C.struct_GetCommentsResult{Err: C.CString(errFilePtr)}
1200+
}
1201+
comments, err := f.(*excelize.File).GetComments(C.GoString(sheet))
1202+
if err != nil {
1203+
return C.struct_GetCommentsResult{Err: C.CString(err.Error())}
1204+
}
1205+
cArray := C.malloc(C.size_t(len(comments)) * C.size_t(unsafe.Sizeof(C.struct_Comment{})))
1206+
for i, r := range comments {
1207+
cVal, err := goValueToC(reflect.ValueOf(r), reflect.ValueOf(&C.struct_Comment{}))
1208+
if err != nil {
1209+
return C.struct_GetCommentsResult{Err: C.CString(err.Error())}
1210+
}
1211+
*(*C.struct_Comment)(unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(C.struct_Comment{}))) = cVal.Elem().Interface().(C.struct_Comment)
1212+
}
1213+
return C.struct_GetCommentsResult{CommentsLen: C.int(len(comments)), Comments: (*C.struct_Comment)(cArray), Err: C.CString(emptyString)}
1214+
}
1215+
11921216
// GetDefaultFont provides the default font name currently set in the
11931217
// workbook. The spreadsheet generated by excelize default font is Calibri.
11941218
//
@@ -1302,6 +1326,56 @@ func GetSheetIndex(idx int, sheet *C.char) C.struct_IntErrorResult {
13021326
return C.struct_IntErrorResult{val: C.int(idx), err: C.CString(emptyString)}
13031327
}
13041328

1329+
// GetSheetList provides a function to get worksheets, chart sheets, and
1330+
// dialog sheets name list of the workbook.
1331+
//
1332+
//export GetSheetList
1333+
func GetSheetList(idx int) C.struct_StringArrayErrorResult {
1334+
f, ok := files.Load(idx)
1335+
if !ok {
1336+
return C.struct_StringArrayErrorResult{Err: C.CString(errFilePtr)}
1337+
}
1338+
result := f.(*excelize.File).GetSheetList()
1339+
cArray := C.malloc(C.size_t(len(result)) * C.size_t(unsafe.Sizeof(uintptr(0))))
1340+
for i, v := range result {
1341+
*(*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(uintptr(0)))) = unsafe.Pointer(C.CString(v))
1342+
}
1343+
return C.struct_StringArrayErrorResult{ArrLen: C.int(len(result)), Arr: (**C.char)(cArray), Err: C.CString(emptyString)}
1344+
}
1345+
1346+
// GetSheetMap provides a function to get worksheets, chart sheets, dialog
1347+
// sheets ID and name map of the workbook.
1348+
//
1349+
//export GetSheetMap
1350+
func GetSheetMap(idx int) C.struct_GetSheetMapResult {
1351+
type IntStringResult struct {
1352+
K int
1353+
V string
1354+
}
1355+
type GetSheetMapResult struct {
1356+
Arr []IntStringResult
1357+
Err string
1358+
}
1359+
var result GetSheetMapResult
1360+
f, ok := files.Load(idx)
1361+
if !ok {
1362+
return C.struct_GetSheetMapResult{
1363+
Err: C.CString(errFilePtr),
1364+
}
1365+
}
1366+
for k, v := range f.(*excelize.File).GetSheetMap() {
1367+
result.Arr = append(result.Arr, IntStringResult{K: k, V: v})
1368+
}
1369+
1370+
cVal, err := goValueToC(reflect.ValueOf(result), reflect.ValueOf(&C.struct_GetSheetMapResult{}))
1371+
if err != nil {
1372+
return C.struct_GetSheetMapResult{Err: C.CString(err.Error())}
1373+
}
1374+
ret := cVal.Elem().Interface().(C.struct_GetSheetMapResult)
1375+
ret.Err = C.CString(emptyString)
1376+
return ret
1377+
}
1378+
13051379
// GetSheetName provides a function to get the sheet name by the given worksheet index.
13061380
// If the given worksheet index is invalid, it will return an error.
13071381
//

test_excelize.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ def test_style(self):
337337
with self.assertRaises(RuntimeError) as context:
338338
_ = f.get_sheet_index("")
339339
self.assertEqual(str(context.exception), "the sheet name can not be blank")
340+
self.assertEqual(f.get_sheet_list(), ["Sheet1", "Sheet2"])
341+
self.assertEqual(len(f.get_sheet_map()), 2)
340342
self.assertEqual(f.get_sheet_name(index), "Sheet2")
341343

342344
self.assertIsNone(f.set_col_outline_level("Sheet1", "D", 2))
@@ -735,6 +737,15 @@ def test_comment(self):
735737
comment,
736738
)
737739
)
740+
comments = f.get_comments("Sheet1")
741+
self.assertEqual(len(comments), 1)
742+
self.assertEqual(comments[0].cell, "A5")
743+
self.assertEqual(comments[0].author, "Excelize")
744+
self.assertEqual(comments[0].paragraph[0].text, comment.paragraph[0].text)
745+
self.assertEqual(comments[0].paragraph[1].text, comment.paragraph[1].text)
746+
with self.assertRaises(RuntimeError) as context:
747+
f.get_comments("SheetN")
748+
self.assertEqual(str(context.exception), "sheet SheetN does not exist")
738749
with self.assertRaises(RuntimeError) as context:
739750
f.add_comment("SheetN", comment)
740751
self.assertEqual(str(context.exception), "sheet SheetN does not exist")

types_c.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,11 @@ struct StringArrayErrorResult
741741
char *Err;
742742
};
743743

744+
struct IntStringResult {
745+
int K;
746+
char *V;
747+
};
748+
744749
struct GetCellHyperLinkResult
745750
{
746751
bool link;
@@ -799,3 +804,15 @@ struct GetWorkbookPropsResult
799804
struct WorkbookPropsOptions opts;
800805
char *err;
801806
};
807+
808+
struct GetSheetMapResult {
809+
int ArrLen;
810+
struct IntStringResult *Arr;
811+
char *Err;
812+
};
813+
814+
struct GetCommentsResult {
815+
int CommentsLen;
816+
struct Comment *Comments;
817+
char *Err;
818+
};

types_go.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,12 +704,21 @@ class _BoolErrorResult(Structure):
704704
("err", c_char_p),
705705
]
706706

707+
707708
class _Float64ErrorResult(Structure):
708709
_fields_ = [
709710
("val", c_double),
710711
("err", c_char_p),
711712
]
712713

714+
715+
class _IntStringResult(Structure):
716+
_fields_ = [
717+
("K", c_int),
718+
("V", c_char_p),
719+
]
720+
721+
713722
class _StringArrayErrorResult(Structure):
714723
_fields_ = [
715724
("ArrLen", c_int),
@@ -784,3 +793,19 @@ class _GetWorkbookPropsResult(Structure):
784793
("opts", _WorkbookPropsOptions),
785794
("err", c_char_p),
786795
]
796+
797+
798+
class _GetSheetMapResult(Structure):
799+
_fields_ = [
800+
("ArrLen", c_int),
801+
("Arr", POINTER(_IntStringResult)),
802+
("Err", c_char_p),
803+
]
804+
805+
806+
class _GetCommentsResult(Structure):
807+
_fields_ = [
808+
("CommentsLen", c_int),
809+
("Comments", POINTER(_Comment)),
810+
("Err", c_char_p),
811+
]

types_py.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,25 @@ class WorkbookProtectionOptions:
792792
lock_windows: bool = False
793793

794794

795+
@dataclass
796+
class IntStringResult:
797+
k: int = 0
798+
v: str = ""
799+
800+
795801
@dataclass
796802
class StringArrayErrorResult:
797803
arr: Optional[List[str]] = None
798804
err: str = ""
805+
806+
807+
@dataclass
808+
class GetSheetMapResult:
809+
arr: Optional[List[IntStringResult]] = None
810+
err: str = ""
811+
812+
813+
@dataclass
814+
class GetCommentsResult:
815+
comments: Optional[List[Comment]] = None
816+
err: str = ""

0 commit comments

Comments
 (0)