Skip to content

Commit

Permalink
Merge pull request #5810 from VesnaT/excel_write_file
Browse files Browse the repository at this point in the history
[FIX] ExcelReader: Write roles
  • Loading branch information
janezd authored Feb 3, 2022
2 parents aa14e94 + ee88eeb commit bd737a6
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
19 changes: 14 additions & 5 deletions Orange/data/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ class ExcelReader(_BaseExcelReader):
EXTENSIONS = ('.xlsx',)
DESCRIPTION = 'Microsoft Excel spreadsheet'
ERRORS = ("#VALUE!", "#DIV/0!", "#REF!", "#NUM!", "#NULL!", "#NAME?")
OPTIONAL_TYPE_ANNOTATIONS = True

def __init__(self, filename):
super().__init__(filename)
Expand Down Expand Up @@ -319,7 +320,7 @@ def _get_active_sheet(self) -> openpyxl.worksheet.worksheet.Worksheet:
return self.workbook.active

@classmethod
def write_file(cls, filename, data):
def write_file(cls, filename, data, with_annotations=False):
vars = list(chain((ContinuousVariable('_w'),) if data.has_weights() else (),
data.domain.attributes,
data.domain.class_vars,
Expand All @@ -329,12 +330,20 @@ def write_file(cls, filename, data):
data.X,
data.Y if data.Y.ndim > 1 else data.Y[:, np.newaxis],
data.metas)
headers = cls.header_names(data)
names = cls.header_names(data)
headers = (names,)
if with_annotations:
types = cls.header_types(data)
flags = cls.header_flags(data)
headers = (names, types, flags)

workbook = xlsxwriter.Workbook(filename)
sheet = workbook.add_worksheet()
for c, header in enumerate(headers):
sheet.write(0, c, header)
for i, row in enumerate(zipped_list_data, 1):

for r, parts in enumerate(headers):
for c, part in enumerate(parts):
sheet.write(r, c, part)
for i, row in enumerate(zipped_list_data, len(headers)):
for j, (fmt, v) in enumerate(zip(formatters, flatten(row))):
sheet.write(i, j, fmt(v))
workbook.close()
Expand Down
30 changes: 30 additions & 0 deletions Orange/tests/test_xlsx_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import unittest
import os
from functools import wraps
from tempfile import mkstemp
from typing import Callable

import numpy as np
Expand Down Expand Up @@ -46,6 +47,35 @@ def test_read_round_floats(self):
self.assertIsInstance(domain[1], ContinuousVariable)
self.assertEqual(domain[2].values, ("1", "2"))

def test_write_file(self):
fd, filename = mkstemp(suffix=".xlsx")
os.close(fd)

data = Table("zoo")
io.ExcelReader.write_file(filename, data, with_annotations=True)

reader = io.ExcelReader(filename)
read_data = reader.read()

domain1 = data.domain
domain2 = read_data.domain
self.assertEqual(len(domain1.attributes), len(domain2.attributes))
self.assertEqual(len(domain1.class_vars), len(domain2.class_vars))
self.assertEqual(len(domain1.metas), len(domain2.metas))
for var1, var2 in zip(domain1.variables + domain1.metas,
domain2.variables + domain2.metas):
self.assertEqual(type(var1), type(var2))
self.assertEqual(var1.name, var2.name)
if var1.is_discrete:
self.assertEqual(var1.values, var2.values)

np.testing.assert_array_equal(data.X, read_data.X)
np.testing.assert_array_equal(data.Y, read_data.Y)
np.testing.assert_array_equal(data.metas, read_data.metas)
np.testing.assert_array_equal(data.W, read_data.W)

os.unlink(filename)


class TestExcelHeader0(unittest.TestCase):
@test_xlsx_xls
Expand Down
8 changes: 7 additions & 1 deletion Orange/widgets/data/owsave.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class OWSave(OWSaveBase):
category = "Data"
keywords = ["export"]

settings_version = 2
settings_version = 3

class Inputs:
data = Input("Data", Table)
Expand Down Expand Up @@ -120,6 +120,12 @@ def migrate_to_version_2():
if version < 2:
migrate_to_version_2()

if version < 3:
if settings.get("add_type_annotations") and \
settings.get("stored_name") and \
os.path.splitext(settings["stored_name"])[1] == ".xlsx":
settings["add_type_annotations"] = False

def initial_start_dir(self):
if self.filename and os.path.exists(os.path.split(self.filename)[0]):
return self.filename
Expand Down
25 changes: 25 additions & 0 deletions Orange/widgets/data/tests/test_owsave.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,31 @@ def test_migration_to_version_2(self):
OWSave.migrate_settings(settings)
self.assertTrue(settings["filter"] in OWSave.get_filters())

def test_migration_to_version_3(self):
settings = {"add_type_annotations": True,
"stored_name": "zoo.xlsx",
"__version__": 2}
widget = self.create_widget(OWSave, stored_settings=settings)
self.assertFalse(widget.add_type_annotations)

settings = {"add_type_annotations": True,
"stored_name": "zoo.tab",
"__version__": 2}
widget = self.create_widget(OWSave, stored_settings=settings)
self.assertTrue(widget.add_type_annotations)

settings = {"add_type_annotations": False,
"stored_name": "zoo.xlsx",
"__version__": 2}
widget = self.create_widget(OWSave, stored_settings=settings)
self.assertFalse(widget.add_type_annotations)

settings = {"add_type_annotations": False,
"stored_name": "zoo.tab",
"__version__": 2}
widget = self.create_widget(OWSave, stored_settings=settings)
self.assertFalse(widget.add_type_annotations)


class TestFunctionalOWSave(WidgetTest):
def setUp(self):
Expand Down

0 comments on commit bd737a6

Please sign in to comment.