Skip to content

Commit d329cb8

Browse files
committed
BUG: boolean/string value in OdsWriter (#54994)
1 parent faeedad commit d329cb8

File tree

3 files changed

+69
-8
lines changed

3 files changed

+69
-8
lines changed

doc/source/whatsnew/v2.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ MultiIndex
228228
I/O
229229
^^^
230230
- Bug in :func:`read_excel`, with ``engine="xlrd"`` (``xls`` files) erroring when file contains NaNs/Infs (:issue:`54564`)
231+
- Bug in :func:`to_excel`, with ``OdsWriter`` (``ods`` files) writing boolean/string value (:issue:`54994`)
231232

232233
Period
233234
^^^^^^

pandas/io/excel/_odswriter.py

+19-8
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,15 @@ def _make_table_cell(self, cell) -> tuple[object, Any]:
192192
if isinstance(val, bool):
193193
value = str(val).lower()
194194
pvalue = str(val).upper()
195-
if isinstance(val, datetime.datetime):
195+
return (
196+
pvalue,
197+
TableCell(
198+
valuetype="boolean",
199+
booleanvalue=value,
200+
attributes=attributes,
201+
),
202+
)
203+
elif isinstance(val, datetime.datetime):
196204
# Fast formatting
197205
value = val.isoformat()
198206
# Slow but locale-dependent
@@ -210,17 +218,20 @@ def _make_table_cell(self, cell) -> tuple[object, Any]:
210218
pvalue,
211219
TableCell(valuetype="date", datevalue=value, attributes=attributes),
212220
)
221+
elif isinstance(val, str):
222+
return (
223+
pvalue,
224+
TableCell(
225+
valuetype="string",
226+
stringvalue=value,
227+
attributes=attributes,
228+
),
229+
)
213230
else:
214-
class_to_cell_type = {
215-
str: "string",
216-
int: "float",
217-
float: "float",
218-
bool: "boolean",
219-
}
220231
return (
221232
pvalue,
222233
TableCell(
223-
valuetype=class_to_cell_type[type(val)],
234+
valuetype="float",
224235
value=value,
225236
attributes=attributes,
226237
),

pandas/tests/io/excel/test_odswriter.py

+49
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
from datetime import (
2+
date,
3+
datetime,
4+
)
15
import re
26

37
import pytest
48

9+
import pandas as pd
510
import pandas._testing as tm
611

712
from pandas.io.excel import ExcelWriter
@@ -47,3 +52,47 @@ def test_book_and_sheets_consistent(ext):
4752
table = odf.table.Table(name="test_name")
4853
writer.book.spreadsheet.addElement(table)
4954
assert writer.sheets == {"test_name": table}
55+
56+
57+
@pytest.mark.parametrize(
58+
["value", "cell_value_type", "cell_value_attribute", "cell_value"],
59+
argvalues=[
60+
(True, "boolean", "boolean-value", "true"),
61+
("test string", "string", "string-value", "test string"),
62+
(1, "float", "value", "1"),
63+
(1.5, "float", "value", "1.5"),
64+
(
65+
datetime(2010, 10, 10, 10, 10, 10),
66+
"date",
67+
"date-value",
68+
"2010-10-10T10:10:10",
69+
),
70+
(date(2010, 10, 10), "date", "date-value", "2010-10-10"),
71+
],
72+
)
73+
def test_cell_value_type(ext, value, cell_value_type, cell_value_attribute, cell_value):
74+
# GH#54994 ODS: cell attributes should follow specification
75+
# http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#refTable13
76+
from odf.namespaces import OFFICENS
77+
from odf.table import (
78+
TableCell,
79+
TableRow,
80+
)
81+
82+
table_cell_name = TableCell().qname
83+
84+
with tm.ensure_clean(ext) as f:
85+
pd.DataFrame([[value]]).to_excel(f, header=False, index=False)
86+
87+
with pd.ExcelFile(f) as wb:
88+
sheet = wb._reader.get_sheet_by_index(0)
89+
sheet_rows = sheet.getElementsByType(TableRow)
90+
sheet_cells = [
91+
x
92+
for x in sheet_rows[0].childNodes
93+
if hasattr(x, "qname") and x.qname == table_cell_name
94+
]
95+
96+
cell = sheet_cells[0]
97+
assert cell.attributes.get((OFFICENS, "value-type")) == cell_value_type
98+
assert cell.attributes.get((OFFICENS, cell_value_attribute)) == cell_value

0 commit comments

Comments
 (0)