From 4090f66e79ce1f8f47fea6344249b4221fec70e1 Mon Sep 17 00:00:00 2001 From: John McNamara Date: Sat, 27 Mar 2021 00:48:54 +0000 Subject: [PATCH] Fix for format with pattern only. Fix issue where pattern formats without colours where given a default black fill colour. --- src/styles.c | 19 +++++++++++++----- test/functional/src/test_format16.c | 23 ++++++++++++++++++++++ test/functional/src/test_format17.c | 24 +++++++++++++++++++++++ test/functional/test_formatting.py | 6 ++++++ test/functional/xlsx_files/format16.xlsx | Bin 0 -> 7030 bytes test/functional/xlsx_files/format17.xlsx | Bin 0 -> 7048 bytes 6 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 test/functional/src/test_format16.c create mode 100644 test/functional/src/test_format17.c create mode 100644 test/functional/xlsx_files/format16.xlsx create mode 100644 test/functional/xlsx_files/format17.xlsx diff --git a/src/styles.c b/src/styles.c index de4d4658..72b8e0e9 100644 --- a/src/styles.c +++ b/src/styles.c @@ -641,7 +641,7 @@ _write_fg_color(lxw_styles *self, lxw_color_t color) * Write the element. */ STATIC void -_write_bg_color(lxw_styles *self, lxw_color_t color) +_write_bg_color(lxw_styles *self, lxw_color_t color, uint8_t pattern) { struct xml_attribute_list attributes; struct xml_attribute *attribute; @@ -650,15 +650,17 @@ _write_bg_color(lxw_styles *self, lxw_color_t color) LXW_INIT_ATTRIBUTES(); if (color == LXW_COLOR_UNSET) { - LXW_PUSH_ATTRIBUTES_STR("indexed", "64"); + if (pattern <= LXW_PATTERN_SOLID) { + LXW_PUSH_ATTRIBUTES_STR("indexed", "64"); + lxw_xml_empty_tag(self->file, "bgColor", &attributes); + } } else { lxw_snprintf(rgb_str, LXW_ATTR_32, "FF%06X", color & LXW_COLOR_MASK); LXW_PUSH_ATTRIBUTES_STR("rgb", rgb_str); + lxw_xml_empty_tag(self->file, "bgColor", &attributes); } - lxw_xml_empty_tag(self->file, "bgColor", &attributes); - LXW_FREE_ATTRIBUTES(); } @@ -704,6 +706,13 @@ _write_fill(lxw_styles *self, lxw_format *format, uint8_t is_dxf) LXW_INIT_ATTRIBUTES(); + /* Special handling for pattern only case. */ + if (!bg_color && !fg_color && pattern) { + _write_default_fill(self, patterns[pattern]); + LXW_FREE_ATTRIBUTES(); + return; + } + lxw_xml_start_tag(self->file, "fill", NULL); /* None/Solid patterns are handled differently for dxf formats. */ @@ -715,7 +724,7 @@ _write_fill(lxw_styles *self, lxw_format *format, uint8_t is_dxf) if (fg_color != LXW_COLOR_UNSET) _write_fg_color(self, fg_color); - _write_bg_color(self, bg_color); + _write_bg_color(self, bg_color, pattern); lxw_xml_end_tag(self->file, "patternFill"); lxw_xml_end_tag(self->file, "fill"); diff --git a/test/functional/src/test_format16.c b/test/functional/src/test_format16.c new file mode 100644 index 00000000..e532b580 --- /dev/null +++ b/test/functional/src/test_format16.c @@ -0,0 +1,23 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_format16.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + lxw_format *pattern = workbook_add_format(workbook); + format_set_pattern(pattern, LXW_PATTERN_MEDIUM_GRAY); + + worksheet_write_string(worksheet, CELL("A1"), "", pattern); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_format17.c b/test/functional/src/test_format17.c new file mode 100644 index 00000000..b29b9974 --- /dev/null +++ b/test/functional/src/test_format17.c @@ -0,0 +1,24 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_format17.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + lxw_format *pattern = workbook_add_format(workbook); + format_set_pattern(pattern, LXW_PATTERN_MEDIUM_GRAY); + format_set_fg_color(pattern, LXW_COLOR_RED); + + worksheet_write_string(worksheet, CELL("A1"), "", pattern); + + return workbook_close(workbook); +} diff --git a/test/functional/test_formatting.py b/test/functional/test_formatting.py index c8712a0f..f70ee46f 100644 --- a/test/functional/test_formatting.py +++ b/test/functional/test_formatting.py @@ -40,6 +40,12 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest): def test_format15(self): self.run_exe_test('test_format15') + def test_format16(self): + self.run_exe_test('test_format16') + + def test_format17(self): + self.run_exe_test('test_format17') + def test_format50(self): self.run_exe_test('test_format50') diff --git a/test/functional/xlsx_files/format16.xlsx b/test/functional/xlsx_files/format16.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..472fcac7cc9857be488db280722f5a4c5c0c84aa GIT binary patch literal 7030 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 B8o2-f literal 0 HcmV?d00001 diff --git a/test/functional/xlsx_files/format17.xlsx b/test/functional/xlsx_files/format17.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a9e1b784100970b90dd2b983bb7e000719626d53 GIT binary patch literal 7048 zcmeHMg7LrPNe zjox>k_j>R92j07TzVGZg-#Neaop0^m+H0-fR)=6*BLiRoZ~y=R1E9};B}Wwv0KmBh z0FVMcq3O#yI=Dd{+>EuooS?3Tyq@-U^tsb$?AZWx)cgO8|2+@9itkl@$A3fqSn)h) znI~elN(M)GE3k{CiJi{mi<0>$pV!RrrBr+{V*prQN2HR`cKe06t5m9et2uSIwR!Qk zhf!id*?E`6nqnp3=sDU2Bl9CY_`)$|Xd(|9L0oFmE}Iq%!jx_1cfB)a zi9%k$KInk^AL|smHsY>?+LEUuAMh*j8?mZnbFFN2u-KszauWph$MYs^FzG zf8&==dj}W*z||E7K>bhARjb3#bcmviGAelR0sUykE>JsHKHl$F`rP;bMAiRHG)2V? zpn`}1xue)3yL7hUpoo)G(5$T3%%DyCmU)}5Had@4=J+TWBM@vpJ#@4>a7TY`d&NeZ zj>e2n^<5MD-AX|-pYg|@Wm&pJ*=CGZHe_8?&uB~^%+A>vd*&ykn~k3pS4BorH6@%g znF#^a$nf{RxD>?lYrHqL9*VzJ44p|>mV&>bRp$YXA|B&l`(T$!pMt(s)eEUOdh)IK znI)@6$z+mB_IfPKTH==sOc$r!>s1OO-_IB!?m1&L$H-)zGEh6XsuOc&goF<&&hLXh zMYzgrZU*pXS(lu&_JbCRf_#Ge<|;@44jP)W7zf`lzh)|2%0IkJg4hO z3bu?Jdt&@Ka8^c9WD=(wYu1(79(HFjTa~QwSXDN5IlEiW__%y@SH}<38fbRATqFpV zZ^{Ta{B}}tk&jT6=rE*vSa7q8N+Na_-d&eBzz`-Hb0P)0`tqRs!lPro3}t`OJ6Dejvw<1&2N-YYfg^h2N7!FQT+HL zGooS*)!xyQ!FN>7iGqC;^y?*(YavloFmvUMY2l=i#Hf21A04jdFd#*9UhZOapp0W^ zqeNYVZ-D#oT3}&(Fv(ydvE~l`X{A?Ns@4K%Jdi6dC!5X5O~=TX2iu$|3rT~6Uc+U* z=vQyjr$bmXqoRyWC0Sd^bDT0I<@y4X*8pQ)zq5+DN3XY_(5k)tGSqbAk?yW_X&dI& zzzzHeAA?WARjxG#W15JgS7E#5KFd7Ye%cA_+vo8yv~qWgQqs^a$?QH!9cYGZbEj(P z8p*ZkF=nr{ex*(j9UgjZmj?ApA<(sBA=qBkRP1qPtL4XFT(#b^>C;?_XQ=bgJi*fN za(PnH`gBILEgM$vH4}8vu7I(ZN*VraV=kzK<5D}!mh7ojbBt$&Z7lp^!n16l^qx3F z2f|JQva{H6lD901^66irGDw=xWd!AQJXC#0_?y>V-Ms9euHU0EK?@Nv!%xskaY}?d zcCgfJs$uD;y;(>$r8&WIu+gE4q@PCU!j;~%RmH1R6*>5YLFK*uz2jbnrek`HGEnVY zyE6wA8!110-(a+BygJhSJVQP~RcTihUwXZpZlm6@G>mkuC~~YDr(GVw7xr#7H*8B@ z|JKfVHt=HIw}NDy@|5xVT?n~WTu3g6W*eU?deMESy&-%XMGrh;MToiCgLAO)k3 zI-3Y=_%$`TsxGCMt6>Vbg}AIC?!#0mmatTs)FBe9=zRw9NVnxGd9VP0E8sXBAinW9 zCQPD%6gXj)RTNMT%SRH#FJ2PQVv7TNiC(K!JW3t%]sc+!^`+D3dXw<*JAzO`1M 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