From 07b182962f692a9f89b89069e35804cd7bc7419c Mon Sep 17 00:00:00 2001 From: John McNamara Date: Mon, 30 Dec 2013 00:57:53 +0000 Subject: [PATCH] Added support for non-contiguous chart ranges. Issue #44. --- dev/docs/source/chart.rst | 7 ++ .../test/comparison/test_chart_column07.py | 81 +++++++++++++++++ .../test/comparison/test_chart_column08.py | 83 ++++++++++++++++++ .../comparison/xlsx_files/chart_column07.xlsx | Bin 0 -> 9178 bytes .../comparison/xlsx_files/chart_column08.xlsx | Bin 0 -> 9230 bytes xlsxwriter/workbook.py | 24 +++-- 6 files changed, 187 insertions(+), 8 deletions(-) create mode 100644 xlsxwriter/test/comparison/test_chart_column07.py create mode 100644 xlsxwriter/test/comparison/test_chart_column08.py create mode 100644 xlsxwriter/test/comparison/xlsx_files/chart_column07.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/chart_column08.xlsx diff --git a/dev/docs/source/chart.rst b/dev/docs/source/chart.rst index fc831788e..bdeacd3c0 100644 --- a/dev/docs/source/chart.rst +++ b/dev/docs/source/chart.rst @@ -223,6 +223,13 @@ More than one series can be added to a chart. In fact, some chart types such as ``stock`` require it. The series numbering and order in the Excel chart will be the same as the order in which they are added in XlsxWriter. +It is also possible to specify non-contiguous ranges:: + + chart.add_series({ + 'categories': '=(Sheet1!$A$1:$A$9,Sheet1!$A$14:$A$25)', + 'values': '=(Sheet1!$B$1:$B$9,Sheet1!$B$14:$B$25)', + }) + chart.set_x_axis() ------------------ diff --git a/xlsxwriter/test/comparison/test_chart_column07.py b/xlsxwriter/test/comparison/test_chart_column07.py new file mode 100644 index 000000000..d1291d63d --- /dev/null +++ b/xlsxwriter/test/comparison/test_chart_column07.py @@ -0,0 +1,81 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# Copyright (c), 2013, John McNamara, jmcnamara@cpan.org +# + +import unittest +import os +from ...workbook import Workbook +from ..helperfunctions import _compare_xlsx_files + + +class TestCompareXLSXFiles(unittest.TestCase): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + self.maxDiff = None + + filename = 'chart_column07.xlsx' + + test_dir = 'xlsxwriter/test/comparison/' + self.got_filename = test_dir + '_test_' + filename + self.exp_filename = test_dir + 'xlsx_files/' + filename + + self.ignore_files = [] + self.ignore_elements = {} + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file.""" + filename = self.got_filename + + #################################################### + + workbook = Workbook(filename) + + worksheet = workbook.add_worksheet() + chart = workbook.add_chart({'type': 'column'}) + + chart.axis_ids = [68810240, 68811776] + + data = [ + [1, 2, 3, 4, 5], + [2, 4, 6, 8, 10], + [3, 6, 9, 12, 15], + + ] + + worksheet.write_column('A1', data[0]) + worksheet.write_column('B1', data[1]) + worksheet.write_column('C1', data[2]) + + chart.add_series({ + 'values': '=(Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5)', + 'values_data': [1, 2, 4, 5], + }) + + worksheet.insert_chart('E9', chart) + + workbook.close() + + #################################################### + + got, exp = _compare_xlsx_files(self.got_filename, + self.exp_filename, + self.ignore_files, + self.ignore_elements) + + self.assertEqual(got, exp) + + def tearDown(self): + # Cleanup. + if os.path.exists(self.got_filename): + os.remove(self.got_filename) + + +if __name__ == '__main__': + unittest.main() diff --git a/xlsxwriter/test/comparison/test_chart_column08.py b/xlsxwriter/test/comparison/test_chart_column08.py new file mode 100644 index 000000000..31c74a02e --- /dev/null +++ b/xlsxwriter/test/comparison/test_chart_column08.py @@ -0,0 +1,83 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# Copyright (c), 2013, John McNamara, jmcnamara@cpan.org +# + +import unittest +import os +from ...workbook import Workbook +from ..helperfunctions import _compare_xlsx_files + + +class TestCompareXLSXFiles(unittest.TestCase): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + self.maxDiff = None + + filename = 'chart_column08.xlsx' + + test_dir = 'xlsxwriter/test/comparison/' + self.got_filename = test_dir + '_test_' + filename + self.exp_filename = test_dir + 'xlsx_files/' + filename + + self.ignore_files = [] + self.ignore_elements = {} + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file.""" + filename = self.got_filename + + #################################################### + + workbook = Workbook(filename) + + worksheet = workbook.add_worksheet() + chart = workbook.add_chart({'type': 'column'}) + + chart.axis_ids = [68809856, 68811392] + + data = [ + [1, 2, 3, 4, 5], + [2, 4, 6, 8, 10], + [3, 6, 9, 12, 15], + + ] + + worksheet.write_column('A1', data[0]) + worksheet.write_column('B1', data[1]) + worksheet.write_column('C1', data[2]) + + chart.add_series({ + 'categories': '=(Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5)', + 'values': '=(Sheet1!$B$1:$B$2,Sheet1!$B$4:$B$5)', + 'categories_data': [1, 2, 4, 5], + 'values_data': [2, 4, 8, 10], + }) + + worksheet.insert_chart('E9', chart) + + workbook.close() + + #################################################### + + got, exp = _compare_xlsx_files(self.got_filename, + self.exp_filename, + self.ignore_files, + self.ignore_elements) + + self.assertEqual(got, exp) + + def tearDown(self): + # Cleanup. + if os.path.exists(self.got_filename): + os.remove(self.got_filename) + + +if __name__ == '__main__': + unittest.main() diff --git a/xlsxwriter/test/comparison/xlsx_files/chart_column07.xlsx b/xlsxwriter/test/comparison/xlsx_files/chart_column07.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..871856bd1a277405d57859fcb777d0916cc1722b GIT binary patch literal 9178 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 literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/chart_column08.xlsx b/xlsxwriter/test/comparison/xlsx_files/chart_column08.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..41c37def0174cc45977267554313729669e32eb4 GIT binary patch literal 9230 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 literal 0 HcmV?d00001 diff --git a/xlsxwriter/workbook.py b/xlsxwriter/workbook.py index 257f4f6f9..e16cdce76 100644 --- a/xlsxwriter/workbook.py +++ b/xlsxwriter/workbook.py @@ -1038,11 +1038,22 @@ def _add_chart_data(self): if sheetname is None: continue - # Die if the name is unknown since it indicates a user error in - # a chart series formula. + # Handle non-contiguous ranges like: + # (Sheet1!$A$1:$A$2,Sheet1!$A$4:$A$5). + # We don't try to parse them. We just return an empty list. + if sheetname.startswith('('): + chart.formula_data[r_id] = [] + seen_ranges[c_range] = [] + continue + + # Warn if the name is unknown since it indicates a user error + # in a chart series formula. if not sheetname in worksheets: warn("Unknown worksheet reference '%s' in range " "'%s' passed to add_series()" % (sheetname, c_range)) + chart.formula_data[r_id] = [] + seen_ranges[c_range] = [] + continue # Find the worksheet object based on the sheet name. worksheet = worksheets[sheetname] @@ -1050,10 +1061,7 @@ def _add_chart_data(self): # Get the data from the worksheet table. data = worksheet._get_range_data(*cells) - # TODO - # # Ignore rich strings for now. Deparse later if necessary. - # if token =~ m{^} and token =~ m{$}: - # token = '' + # TODO. Handle SST string ids if required. # Add the data to the chart. chart.formula_data[r_id] = data @@ -1069,13 +1077,13 @@ def _get_chart_range(self, c_range): # TODO. Fix this to match from right. pos = c_range.find('!') if pos > 0: - sheetname, cells = c_range.split('!') + sheetname, cells = c_range.split('!', 1) else: return None # Split the cell range into 2 cells or else use single cell for both. if cells.find(':') > 0: - (cell_1, cell_2) = cells.split(':') + (cell_1, cell_2) = cells.split(':', 1) else: (cell_1, cell_2) = (cells, cells)