Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New functions cell_name_to_coordinates, column_name_to_number and column_number_to_name #4

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions excelize.py
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,58 @@ def set_sheet_row(
return None if err == "" else Exception(err)


def cell_name_to_coordinates(cell: str) -> Tuple[int, int, Exception | None]:
"""
Converts alphanumeric cell name to [X, Y] coordinates or returns an error.

Args:
cell (str): The cell reference

Returns:
Tuple[int, int, Exception | None]: A tuple containing the column number,
row number, and an Exception if an error occurred, otherwise None.
"""
lib.CellNameToCoordinates.restype = types_go._CellNameToCoordinatesResult
res = lib.CellNameToCoordinates(cell.encode(ENCODE))
err = res.err.decode(ENCODE)
return res.col, res.row, None if err == "" else Exception(err)


def column_name_to_number(name: str) -> Tuple[int, Exception | None]:
"""
Convert Excel sheet column name (case-insensitive) to int. The function
returns an error if column name incorrect.

Args:
name (str): The column name

Returns:
Tuple[int, Exception | None]: A tuple containing the column number and
an Exception if an error occurred, otherwise None.
"""
lib.ColumnNameToNumber.restype = types_go._ColumnNameToNumberResult
res = lib.ColumnNameToNumber(name.encode(ENCODE))
err = res.err.decode(ENCODE)
return res.col, None if err == "" else Exception(err)


def column_number_to_name(num: int) -> Tuple[str, Exception | None]:
"""
Convert the integer to Excel sheet column title.

Args:
num (int): The column number

Returns:
Tuple[str, Exception | None]: A tuple containing the column name and an
Exception if an error occurred, otherwise None.
"""
lib.ColumnNumberToName.restype = types_go._ColumnNumberToNameResult
res = lib.ColumnNumberToName(c_int(num))
err = res.err.decode(ENCODE)
return res.col.decode(ENCODE), None if err == "" else Exception(err)


def coordinates_to_cell_name(
col: int, row: int, *abs: bool
) -> Tuple[str, Exception | None]:
Expand Down
37 changes: 37 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,43 @@ func AddPicture(idx int, sheet, cell, name *C.char, opts *C.struct_GraphicOption
return C.CString(errNil)
}

// CellNameToCoordinates converts alphanumeric cell name to [X, Y] coordinates
// or returns an error.
//
//export CellNameToCoordinates
func CellNameToCoordinates(cell *C.char) C.struct_CellNameToCoordinatesResult {
col, row, err := excelize.CellNameToCoordinates(C.GoString(cell))
if err != nil {
return C.struct_CellNameToCoordinatesResult{col: C.int(col), row: C.int(row), err: C.CString(err.Error())}
}
return C.struct_CellNameToCoordinatesResult{col: C.int(col), row: C.int(row), err: C.CString(errNil)}
}

// ColumnNameToNumber provides a function to convert Excel sheet column name
// (case-insensitive) to int. The function returns an error if column name
// incorrect.
//
//export ColumnNameToNumber
func ColumnNameToNumber(name *C.char) C.struct_CellNameToCoordinatesResult {
col, err := excelize.ColumnNameToNumber(C.GoString(name))
if err != nil {
return C.struct_CellNameToCoordinatesResult{col: C.int(col), err: C.CString(err.Error())}
}
return C.struct_CellNameToCoordinatesResult{col: C.int(col), err: C.CString(errNil)}
}

// ColumnNumberToName provides a function to convert the integer to Excel
// sheet column title.
//
//export ColumnNumberToName
func ColumnNumberToName(num int) C.struct_ColumnNumberToNameResult {
col, err := excelize.ColumnNumberToName(num)
if err != nil {
return C.struct_ColumnNumberToNameResult{col: C.CString(col), err: C.CString(err.Error())}
}
return C.struct_ColumnNumberToNameResult{col: C.CString(col), err: C.CString(errNil)}
}

// CoordinatesToCellName converts [X, Y] coordinates to alpha-numeric cell name
// or returns an error.
//
Expand Down
38 changes: 38 additions & 0 deletions test_excelize.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,44 @@ def test_add_chart(self):
)
self.assertIsNone(f.save_as("TestAddChart.xlsx"))

def test_cell_name_to_coordinates(self):
col, row, err = excelize.cell_name_to_coordinates("Z3")
self.assertEqual(col, 26)
self.assertEqual(row, 3)
self.assertIsNone(err)

col, row, err = excelize.cell_name_to_coordinates("A")
self.assertEqual(col, -1)
self.assertEqual(row, -1)
self.assertEqual(
err.__str__(),
'cannot convert cell "A" to coordinates: invalid cell name "A"',
)

def test_column_name_to_number(self):
col, err = excelize.column_name_to_number("Z")
self.assertEqual(col, 26)
self.assertIsNone(err)

col, err = excelize.column_name_to_number("-")
self.assertEqual(col, -1)
self.assertEqual(
err.__str__(),
'invalid column name "-"',
)

def test_column_number_to_name(self):
name, err = excelize.column_number_to_name(26)
self.assertEqual(name, "Z")
self.assertIsNone(err)

name, err = excelize.column_number_to_name(0)
self.assertEqual(name, "")
self.assertEqual(
err.__str__(),
"the column number must be greater than or equal to 1 and less than or equal to 16384",
)

def test_add_picture(self):
f = excelize.new_file()
self.assertIsNone(f.add_picture("Sheet1", "A1", "chart.png", None))
Expand Down
16 changes: 16 additions & 0 deletions types_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,22 @@ struct Chart {
int HoleSize;
};

struct CellNameToCoordinatesResult {
int col;
int row;
char* err;
};

struct ColumnNameToNumberResult {
int col;
char* err;
};

struct ColumnNumberToNameResult {
char* col;
char* err;
};

struct CoordinatesToCellNameResult {
char* cell;
char* err;
Expand Down
22 changes: 22 additions & 0 deletions types_go.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,28 @@ class _Chart(Structure):
]


class _CellNameToCoordinatesResult(Structure):
_fields_ = [
("col", c_int),
("row", c_int),
("err", c_char_p),
]


class _ColumnNameToNumberResult(Structure):
_fields_ = [
("col", c_int),
("err", c_char_p),
]


class _ColumnNumberToNameResult(Structure):
_fields_ = [
("col", c_char_p),
("err", c_char_p),
]


class _CoordinatesToCellNameResult(Structure):
_fields_ = [
("cell", c_char_p),
Expand Down
99 changes: 96 additions & 3 deletions types_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@


class CultureName(IntEnum):
"""
This section defines the currently supported country code types enumeration
for apply number format.
"""

CultureNameUnknown = 0
CultureNameEnUS = 1
CultureNameJaJP = 2
Expand All @@ -23,7 +28,52 @@ class CultureName(IntEnum):
CultureNameZhTW = 5


class CellType(IntEnum):
"""
This section defines the cell value types enumeration.
"""

CellTypeUnset = 0
CellTypeBool = 1
CellTypeDate = 2
CellTypeError = 3
CellTypeFormula = 4
CellTypeInlineString = 5
CellTypeNumber = 6
CellTypeSharedString = 7


class FormControlType(IntEnum):
"""
FormControlType is the type of supported form controls.
"""

FormControlNote = 0
FormControlButton = 1
FormControlOptionButton = 2
FormControlSpinButton = 3
FormControlCheckBox = 4
FormControlGroupBox = 5
FormControlLabel = 6
FormControlScrollBar = 7


class ChartLineType(IntEnum):
"""
ChartLineType defines the currently supported chart line types enumeration.
"""

ChartLineUnset = 0
ChartLineSolid = 1
ChartLineNone = 2
ChartLineAutomatic = 3


class ChartType(IntEnum):
"""
ChartType defines the currently supported chart types enumeration.
"""

Area = 0
AreaStacked = 1
AreaPercentStacked = 2
Expand Down Expand Up @@ -81,6 +131,45 @@ class ChartType(IntEnum):
Bubble3D = 54


class ChartDataLabelPositionType(IntEnum):
"""
ChartDataLabelPositionType is the type of chart data labels position.
"""

ChartDataLabelsPositionUnset = 0
ChartDataLabelsPositionBestFit = 1
ChartDataLabelsPositionBelow = 2
ChartDataLabelsPositionCenter = 3
ChartDataLabelsPositionInsideBase = 4
ChartDataLabelsPositionInsideEnd = 5
ChartDataLabelsPositionLeft = 6
ChartDataLabelsPositionOutsideEnd = 7
ChartDataLabelsPositionRight = 8
ChartDataLabelsPositionAbove = 9


class ChartTickLabelPositionType(IntEnum):
"""
ChartTickLabelPositionType is the type of supported chart tick label
"""

ChartTickLabelNextToAxis = 0
ChartTickLabelHigh = 1
ChartTickLabelLow = 2
ChartTickLabelNone = 3


class PictureInsertType(IntEnum):
"""
PictureInsertType defines the type of the picture has been inserted into the
worksheet.
"""

PictureInsertTypePlaceOverCells = 0
PictureInsertTypePlaceInCell = 1
PictureInsertTypeDISPIMG = 2


@dataclass
class Interface:
type: int = 0
Expand Down Expand Up @@ -210,7 +299,9 @@ class ChartAxis:
major_grid_lines: bool = False
minor_grid_lines: bool = False
major_unit: float = 0
tick_label_position: int = 0
tick_label_position: ChartDataLabelPositionType = (
ChartDataLabelPositionType.ChartDataLabelsPositionUnset
)
tick_label_skip: int = 0
reverse_order: bool = False
secondary: bool = False
Expand Down Expand Up @@ -257,7 +348,7 @@ class ChartMarker:

@dataclass
class ChartLine:
type: int = 0
type: ChartLineType = ChartLineType.ChartLineUnset
smooth: bool = False
width: float = 0

Expand All @@ -271,7 +362,9 @@ class ChartSeries:
fill: Fill = Fill
line: ChartLine = ChartLine
marker: ChartMarker = ChartMarker
data_label_position: int = 0
data_label_position: ChartDataLabelPositionType = (
ChartDataLabelPositionType.ChartDataLabelsPositionUnset
)


@dataclass
Expand Down
Loading