Skip to content

Commit

Permalink
Initial working custom chart data labels.
Browse files Browse the repository at this point in the history
Issue #343
  • Loading branch information
jmcnamara committed Jul 24, 2020
1 parent 6368a3f commit c3340b0
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 0 deletions.
113 changes: 113 additions & 0 deletions xlsxwriter/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,24 @@ def _get_labels_properties(self, labels):
# Set the font properties if present.
labels['font'] = self._convert_font_args(labels.get('font'))

if labels.get('custom'):

for label in labels['custom']:
if label is None:
continue

value = label.get('value')
if value and re.match(r'^=?[^!]+!\$?[A-Z]+\$?[0-9]+',
str(value)):
label['formula'] = value

formula = label.get('formula')
if formula and formula.startswith('='):
label['formula'] = formula.lstrip('=')

data_id = self._get_data_id(formula, label.get('data'))
label['data_id'] = data_id

return labels

def _get_area_properties(self, options):
Expand Down Expand Up @@ -2851,6 +2869,35 @@ def _write_rich(self, title, is_y_axis, font):

self._xml_end_tag('c:rich')

def _write_rich_label(self, title, font):
# Write the <c:rich> element for data labels.

if font and font.get('rotation'):
rotation = font['rotation']
else:
rotation = None

self._xml_start_tag('c:rich')

# Write the a:bodyPr element.
self._write_a_body_pr(rotation, None)

# Write the a:lstStyle element.
self._write_a_lst_style()

self._xml_start_tag('a:p')

# Write the a:pPr element.
if font:
self._write_a_p_pr_rich(font)

# Write the a:r element.
self._write_a_r(title, font)

self._xml_end_tag('a:p')

self._xml_end_tag('c:rich')

def _write_a_body_pr(self, rotation, is_y_axis):
# Write the <a:bodyPr> element.
attributes = []
Expand Down Expand Up @@ -3490,6 +3537,10 @@ def _write_d_lbls(self, labels):

self._xml_start_tag('c:dLbls')

# Write the custom c:dLbl elements.
if labels.get('custom'):
self._write_custom_labels(labels['custom'])

# Write the c:numFmt element.
if labels.get('num_format'):
self._write_data_label_number_format(labels['num_format'])
Expand Down Expand Up @@ -3532,6 +3583,68 @@ def _write_d_lbls(self, labels):

self._xml_end_tag('c:dLbls')

def _write_custom_labels(self, labels):
# Write the <c:showLegendKey> element.
index = 0

for label in labels:
index += 1

if label is None:
continue

self._xml_start_tag('c:dLbl')

# Write the c:idx element.
self._write_idx(index - 1)

delete_label = label.get('delete')

if delete_label:
self._write_delete(1)
elif label.get('formula'):
self._write_custom_label_formula(label)
self._write_show_val()
elif label.get('value'):
self._write_custom_label_str(label)
self._write_show_val()

self._xml_end_tag('c:dLbl')

def _write_custom_label_str(self, label):
# Write parts of the <c:dLbl> element for strings.
title = label.get('value')
font = label.get('font')

# Write the c:layout element.
self._write_layout(None, None)

self._xml_start_tag('c:tx')

# Write the c:rich element.
self._write_rich_label(title, font)

self._xml_end_tag('c:tx')

def _write_custom_label_formula(self, label):
# Write parts of the <c:dLbl> element for strings.
formula = label.get('formula')
data_id = label.get('data_id')
data = None

if data_id is not None:
data = self.formula_data[data_id]

# Write the c:layout element.
self._write_layout(None, None)

self._xml_start_tag('c:tx')

# Write the c:strRef element.
self._write_str_ref(formula, data, 'str')

self._xml_end_tag('c:tx')

def _write_show_legend_key(self):
# Write the <c:showLegendKey> element.
val = '1'
Expand Down
56 changes: 56 additions & 0 deletions xlsxwriter/test/comparison/test_chart_data_labels26.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
###############################################################################
#
# Tests for XlsxWriter.
#
# Copyright (c), 2013-2019, John McNamara, jmcnamara@cpan.org
#

from ..excel_comparison_test import ExcelComparisonTest
from ...workbook import Workbook


class TestCompareXLSXFiles(ExcelComparisonTest):
"""
Test file created by XlsxWriter against a file created by Excel.
"""

def setUp(self):

self.set_filename('chart_data_labels26.xlsx')

def test_create_file(self):
"""Test the creation of a simple XlsxWriter file."""

workbook = Workbook(self.got_filename)

worksheet = workbook.add_worksheet()
chart = workbook.add_chart({'type': 'column'})

chart.axis_ids = [48514944, 48516480]

data = [
[1, 2, 3, 4, 5],
[2, 4, 6, 8, 10],
[3, 6, 9, 12, 15],
[10, 20, 30, 40, 50],
]

worksheet.write_column('A1', data[0])
worksheet.write_column('B1', data[1])
worksheet.write_column('C1', data[2])
worksheet.write_column('D1', data[3])

chart.add_series({
'values': '=Sheet1!$A$1:$A$5',
'data_labels': {'value': 1, 'custom': [{'value': 33}]}
})

chart.add_series({'values': '=Sheet1!$B$1:$B$5'})
chart.add_series({'values': '=Sheet1!$C$1:$C$5'})

worksheet.insert_chart('E9', chart)

workbook.close()

self.assertExcelEqual()
56 changes: 56 additions & 0 deletions xlsxwriter/test/comparison/test_chart_data_labels27.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
###############################################################################
#
# Tests for XlsxWriter.
#
# Copyright (c), 2013-2019, John McNamara, jmcnamara@cpan.org
#

from ..excel_comparison_test import ExcelComparisonTest
from ...workbook import Workbook


class TestCompareXLSXFiles(ExcelComparisonTest):
"""
Test file created by XlsxWriter against a file created by Excel.
"""

def setUp(self):

self.set_filename('chart_data_labels27.xlsx')

def test_create_file(self):
"""Test the creation of a simple XlsxWriter file."""

workbook = Workbook(self.got_filename)

worksheet = workbook.add_worksheet()
chart = workbook.add_chart({'type': 'column'})

chart.axis_ids = [48514944, 48516480]

data = [
[1, 2, 3, 4, 5],
[2, 4, 6, 8, 10],
[3, 6, 9, 12, 15],
[10, 20, 30, 40, 50],
]

worksheet.write_column('A1', data[0])
worksheet.write_column('B1', data[1])
worksheet.write_column('C1', data[2])
worksheet.write_column('D1', data[3])

chart.add_series({
'values': '=Sheet1!$A$1:$A$5',
'data_labels': {'value': 1, 'custom': [{'value': '=Sheet1!$D$1'}]}
})

chart.add_series({'values': '=Sheet1!$B$1:$B$5'})
chart.add_series({'values': '=Sheet1!$C$1:$C$5'})

worksheet.insert_chart('E9', chart)

workbook.close()

self.assertExcelEqual()
64 changes: 64 additions & 0 deletions xlsxwriter/test/comparison/test_chart_data_labels28.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
###############################################################################
#
# Tests for XlsxWriter.
#
# Copyright (c), 2013-2019, John McNamara, jmcnamara@cpan.org
#

from ..excel_comparison_test import ExcelComparisonTest
from ...workbook import Workbook


class TestCompareXLSXFiles(ExcelComparisonTest):
"""
Test file created by XlsxWriter against a file created by Excel.
"""

def setUp(self):

self.set_filename('chart_data_labels28.xlsx')

def test_create_file(self):
"""Test the creation of a simple XlsxWriter file."""

workbook = Workbook(self.got_filename)

worksheet = workbook.add_worksheet()
chart = workbook.add_chart({'type': 'column'})

chart.axis_ids = [48514944, 48516480]

data = [
[1, 2, 3, 4, 5],
[2, 4, 6, 8, 10],
[3, 6, 9, 12, 15],
['foo', 'bar'],
]

worksheet.write_column('A1', data[0])
worksheet.write_column('B1', data[1])
worksheet.write_column('C1', data[2])
worksheet.write_column('D1', data[3])

custom = [
{'value': 123},
{'value': 'abc'},
None,
{'formula': 'Sheet1!$D$1'},
{'formula': 'Sheet1!$D$2'}
]

chart.add_series({
'values': '=Sheet1!$A$1:$A$5',
'data_labels': {'value': 1, 'custom': custom}
})

chart.add_series({'values': '=Sheet1!$B$1:$B$5'})
chart.add_series({'values': '=Sheet1!$C$1:$C$5'})

worksheet.insert_chart('E9', chart)

workbook.close()

self.assertExcelEqual()
54 changes: 54 additions & 0 deletions xlsxwriter/test/comparison/test_chart_data_labels29.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
###############################################################################
#
# Tests for XlsxWriter.
#
# Copyright (c), 2013-2019, John McNamara, jmcnamara@cpan.org
#

from ..excel_comparison_test import ExcelComparisonTest
from ...workbook import Workbook


class TestCompareXLSXFiles(ExcelComparisonTest):
"""
Test file created by XlsxWriter against a file created by Excel.
"""

def setUp(self):

self.set_filename('chart_data_labels29.xlsx')

def test_create_file(self):
"""Test the creation of a simple XlsxWriter file."""

workbook = Workbook(self.got_filename)

worksheet = workbook.add_worksheet()
chart = workbook.add_chart({'type': 'column'})

chart.axis_ids = [67858816, 67863296]

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$5',
'data_labels': {'value': 1, 'custom': [{'delete': 1}]}
})

chart.add_series({'values': '=Sheet1!$B$1:$B$5'})
chart.add_series({'values': '=Sheet1!$C$1:$C$5'})

worksheet.insert_chart('E9', chart)

workbook.close()

self.assertExcelEqual()

0 comments on commit c3340b0

Please sign in to comment.