1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <officecfg/Office/Common.hxx>
12 #include "helper/qahelper.hxx"
15 #include <docpool.hxx>
16 #include <scitems.hxx>
18 #include <stlpool.hxx>
19 #include <formulacell.hxx>
21 #include <validat.hxx>
22 #include <scresid.hxx>
23 #include <globstr.hrc>
25 #include <editeng/wghtitem.hxx>
26 #include <editeng/postitem.hxx>
27 #include <editeng/eeitem.hxx>
28 #include <editeng/editobj.hxx>
29 #include <editeng/fhgtitem.hxx>
30 #include <editeng/flditem.hxx>
31 #include <editeng/justifyitem.hxx>
32 #include <comphelper/scopeguard.hxx>
33 #include <formula/grammar.hxx>
34 #include <tools/fldunit.hxx>
35 #include <svl/numformat.hxx>
36 #include <svl/zformat.hxx>
37 #include <svx/svdocapt.hxx>
39 #include <com/sun/star/chart2/XChartDocument.hpp>
40 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
41 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
42 #include <com/sun/star/drawing/LineJoint.hpp>
43 #include <com/sun/star/drawing/XDrawPage.hpp>
44 #include <com/sun/star/drawing/XDrawPages.hpp>
45 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
46 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
47 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
48 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
49 #include <com/sun/star/text/XTextColumns.hpp>
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::uno
;
54 class ScExportTest4
: public ScModelTestBase
60 ScExportTest4::ScExportTest4()
61 : ScModelTestBase("sc/qa/unit/data")
65 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf126177XLSX
)
67 createScDoc("xlsx/hyperlink_export.xlsx");
68 save("Calc Office Open XML");
70 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
72 assertXPath(pDoc
, "/x:worksheet/x:hyperlinks/x:hyperlink"_ostr
, "location"_ostr
, "Munka1!A5");
74 xmlDocUniquePtr pXmlRels
= parseExport("xl/worksheets/_rels/sheet1.xml.rels");
75 CPPUNIT_ASSERT(pXmlRels
);
77 = getXPath(pXmlRels
, "/rels:Relationships/rels:Relationship"_ostr
, "Target"_ostr
);
78 CPPUNIT_ASSERT(aTarget
.endsWith("test.xlsx"));
79 assertXPath(pXmlRels
, "/rels:Relationships/rels:Relationship"_ostr
, "TargetMode"_ostr
,
83 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testCommentTextVAlignment
)
85 // Testing comment text alignments.
86 createScDoc("ods/CommentTextVAlign.ods");
88 save("Calc Office Open XML");
90 xmlDocUniquePtr pVmlDrawing
= parseExport("xl/drawings/vmlDrawing1.vml");
91 CPPUNIT_ASSERT(pVmlDrawing
);
93 assertXPathContent(pVmlDrawing
, "/xml/v:shape/xx:ClientData/xx:TextVAlign"_ostr
, "Center");
96 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testCommentTextHAlignment
)
98 // Testing comment text alignments.
99 createScDoc("ods/CommentTextHAlign.ods");
101 save("Calc Office Open XML");
103 xmlDocUniquePtr pVmlDrawing
= parseExport("xl/drawings/vmlDrawing1.vml");
104 CPPUNIT_ASSERT(pVmlDrawing
);
106 assertXPathContent(pVmlDrawing
, "/xml/v:shape/xx:ClientData/xx:TextHAlign"_ostr
, "Center");
109 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testRotatedImageODS
)
111 // Error was, that the length values in shapes were not
112 // written in the given unit into the file.
113 css::uno::Reference
<css::sheet::XGlobalSheetSettings
> xGlobalSheetSettings
114 = css::sheet::GlobalSheetSettings::create(comphelper::getProcessComponentContext());
115 xGlobalSheetSettings
->setMetric(static_cast<sal_Int16
>(FieldUnit::MM
));
117 createScDoc("ods/tdf103092_RotatedImage.ods");
120 xmlDocUniquePtr pXmlDoc
= parseExport("content.xml");
121 CPPUNIT_ASSERT(pXmlDoc
);
123 const OUString sTransform
= getXPath(pXmlDoc
,
124 "/office:document-content/office:body/office:spreadsheet/"
125 "table:table/table:shapes/draw:frame"_ostr
,
127 // Attribute transform has the structure skew (...) rotate (...) translate (x y)
128 // parts are separated by blank
129 OUString
sTranslate(sTransform
.copy(sTransform
.lastIndexOf('(')));
130 sTranslate
= sTranslate
.copy(1, sTranslate
.getLength() - 2); // remove '(' and ')'
131 const OUString
sX(sTranslate
.getToken(0, ' '));
132 const OUString
sY(sTranslate
.getToken(1, ' '));
133 CPPUNIT_ASSERT(sX
.endsWith("mm"));
134 CPPUNIT_ASSERT(sY
.endsWith("mm"));
137 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf120177
)
139 createScDoc("xls/tdf120177.xls");
141 // Error: unexpected attribute "form:input-required"
145 xmlDocUniquePtr pXmlDoc
= parseExport("content.xml");
146 CPPUNIT_ASSERT(pXmlDoc
);
148 // Without the fix in place, this test would have failed with
149 // no attribute 'value' exist
151 "/office:document-content/office:body/office:spreadsheet/table:table/office:forms/"
152 "form:form/form:radio[1]"_ostr
,
155 "/office:document-content/office:body/office:spreadsheet/table:table/office:forms/"
156 "form:form/form:radio[2]"_ostr
,
158 const OUString sGroupName1
= getXPath(pXmlDoc
,
159 "/office:document-content/office:body/office:spreadsheet/"
160 "table:table/office:forms/form:form/form:radio[1]"_ostr
,
162 const OUString sGroupName2
= getXPath(pXmlDoc
,
163 "/office:document-content/office:body/office:spreadsheet/"
164 "table:table/office:forms/form:form/form:radio[2]"_ostr
,
166 CPPUNIT_ASSERT_EQUAL(sGroupName1
, sGroupName2
);
169 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf85553
)
171 createScDoc("ods/tdf85553.ods");
173 saveAndReload("MS Excel 97");
175 ScDocument
* pDoc
= getScDoc();
177 // Without the fix in place, this test would have failed with
180 CPPUNIT_ASSERT_EQUAL(OUString("4.5"), pDoc
->GetString(ScAddress(2, 2, 0)));
183 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf151484
)
185 std::vector
<OUString
> aFilterNames
{ "calc8", "MS Excel 97", "Calc Office Open XML" };
187 for (size_t i
= 0; i
< aFilterNames
.size(); ++i
)
189 createScDoc("ods/tdf151484.ods");
191 const OString sFailedMessage
192 = OString::Concat("Failed on filter: ") + aFilterNames
[i
].toUtf8();
194 saveAndReload(aFilterNames
[i
]);
196 ScDocument
* pDoc
= getScDoc();
198 const ScValidationData
* pData
= pDoc
->GetValidationEntry(1);
199 CPPUNIT_ASSERT(pData
);
201 std::vector
<ScTypedStrData
> aList
;
202 pData
->FillSelectionList(aList
, ScAddress(0, 1, 0));
204 // Without the fix in place, this test would have failed with
207 // - Failed on filter: MS Excel 97
208 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), size_t(4), aList
.size());
209 for (size_t j
= 0; j
< 4; ++j
)
210 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage
.getStr(), double(j
+ 1),
211 aList
[j
].GetValue());
215 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf143979
)
219 ScDocument
* pDoc
= getScDoc();
220 OUString aCode
= "YYYY-MM\"\"MMM-DDNN";
222 SvNumFormatType nType
;
224 SvNumberFormatter
* pFormatter
= pDoc
->GetFormatTable();
225 pFormatter
->PutEntry(aCode
, nCheckPos
, nType
, nFormat
);
226 ScPatternAttr
aNewAttrs(pDoc
->GetPool());
227 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
228 rSet
.Put(SfxUInt32Item(ATTR_VALUE_FORMAT
, nFormat
));
229 pDoc
->ApplyPattern(0, 0, 0, aNewAttrs
);
230 pDoc
->SetString(ScAddress(0, 0, 0), "08/30/2021");
231 CPPUNIT_ASSERT_EQUAL(OUString("2021-08Aug-30Mon"), pDoc
->GetString(ScAddress(0, 0, 0)));
234 saveAndReload("calc8");
236 ScDocument
* pDoc
= getScDoc();
237 // Without the fix in place, this test would have failed with
238 // - Expected: 2021-08Aug-30Mon
239 // - Actual : 2021-A-30Mon
240 CPPUNIT_ASSERT_EQUAL(OUString("2021-08Aug-30Mon"), pDoc
->GetString(ScAddress(0, 0, 0)));
243 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf128976
)
245 createScDoc("xls/tdf128976.xls");
247 saveAndReload("MS Excel 97");
249 ScDocument
* pDoc
= getScDoc();
251 // Trying to save very small fractional default column width to XLS (where only integer values
252 // between 0 and 255 are allowed as default) resulted in negative (-1) value after correction,
253 // and was written as 65535 (invalid default width). As the result, all columns had large width
254 // when reopened: 28415 (and Excel warned about invalid format).
255 const sal_uInt16 nColumn0Width
= pDoc
->GetColWidth(SCCOL(0), SCTAB(0), false);
256 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(45), nColumn0Width
);
259 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf120502
)
261 // Create an empty worksheet; resize last column on its first sheet; export to XLSX, and check
262 // that the last exported column number is correct
265 ScDocument
* pDoc
= getScDoc();
266 const SCCOL nMaxCol
= pDoc
->MaxCol(); // 0-based
268 const auto nOldWidth
= pDoc
->GetColWidth(nMaxCol
, 0);
269 pDoc
->SetColWidth(nMaxCol
, 0, nOldWidth
+ 100);
271 save("Calc Office Open XML");
272 xmlDocUniquePtr pSheet1
= parseExport("xl/worksheets/sheet1.xml");
273 CPPUNIT_ASSERT(pSheet1
);
275 // This was 1025 when nMaxCol+1 was 1024
276 assertXPath(pSheet1
, "/x:worksheet/x:cols/x:col"_ostr
, "max"_ostr
,
277 OUString::number(nMaxCol
+ 1));
280 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf131372
)
282 createScDoc("ods/tdf131372.ods");
284 save("Calc Office Open XML");
286 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
287 CPPUNIT_ASSERT(pSheet
);
289 assertXPathContent(pSheet
, "/x:worksheet/x:sheetData/x:row/x:c[1]/x:f"_ostr
, "NA()");
290 assertXPathContent(pSheet
, "/x:worksheet/x:sheetData/x:row/x:c[2]/x:f"_ostr
, "#N/A");
292 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf81470
)
294 createScDoc("xls/tdf81470.xls");
296 //without the fix in place, it would have crashed at export time
297 save("Calc Office Open XML");
299 //also check revisions are exported
300 xmlDocUniquePtr pHeaders
= parseExport("xl/revisions/revisionHeaders.xml");
301 CPPUNIT_ASSERT(pHeaders
);
303 assertXPath(pHeaders
, "/x:headers/x:header[1]"_ostr
, "dateTime"_ostr
,
304 "2014-07-11T13:46:00.000000000Z");
305 assertXPath(pHeaders
, "/x:headers/x:header[1]"_ostr
, "userName"_ostr
, "Kohei Yoshida");
306 assertXPath(pHeaders
, "/x:headers/x:header[2]"_ostr
, "dateTime"_ostr
,
307 "2014-07-11T18:38:00.000000000Z");
308 assertXPath(pHeaders
, "/x:headers/x:header[2]"_ostr
, "userName"_ostr
, "Kohei Yoshida");
309 assertXPath(pHeaders
, "/x:headers/x:header[3]"_ostr
, "dateTime"_ostr
,
310 "2014-07-11T18:43:00.000000000Z");
311 assertXPath(pHeaders
, "/x:headers/x:header[3]"_ostr
, "userName"_ostr
, "Kohei Yoshida");
314 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf122331
)
316 createScDoc("ods/tdf122331.ods");
318 save("Calc Office Open XML");
320 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
321 CPPUNIT_ASSERT(pSheet
);
323 assertXPath(pSheet
, "/x:worksheet/x:sheetPr"_ostr
, "filterMode"_ostr
, "true");
324 assertXPath(pSheet
, "/x:worksheet/x:autoFilter"_ostr
, "ref"_ostr
, "A1:B761");
325 assertXPath(pSheet
, "/x:worksheet/x:autoFilter/x:filterColumn"_ostr
, "colId"_ostr
, "1");
328 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf83779
)
330 // Roundtripping TRUE/FALSE constants (not functions) must convert them to functions
331 createScDoc("xlsx/tdf83779.xlsx");
333 save("Calc Office Open XML");
335 xmlDocUniquePtr pVmlDrawing
= parseExport("xl/worksheets/sheet1.xml");
336 CPPUNIT_ASSERT(pVmlDrawing
);
338 assertXPathContent(pVmlDrawing
, "/x:worksheet/x:sheetData/x:row[1]/x:c/x:f"_ostr
, "FALSE()");
339 assertXPathContent(pVmlDrawing
, "/x:worksheet/x:sheetData/x:row[2]/x:c/x:f"_ostr
, "TRUE()");
342 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf121715_FirstPageHeaderFooterXLSX
)
344 // Check if first page header and footer are exported properly
345 createScDoc("xlsx/tdf121715.xlsx");
347 save("Calc Office Open XML");
348 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
349 CPPUNIT_ASSERT(pDoc
);
351 assertXPath(pDoc
, "/x:worksheet/x:headerFooter"_ostr
, "differentFirst"_ostr
, "true");
352 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:firstHeader"_ostr
,
353 "&CFirst Page Header");
354 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:firstFooter"_ostr
,
355 "&CFirst Page Footer");
358 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf121716_ExportEvenHeaderFooterXLSX
)
360 // Header and footer on even pages should be exported properly
361 // If there are separate odd/even header, but only 1 footer for all pages (this is possible only in LibreOffice)
362 // then the footer will be duplicated to have the same footer separately for even/odd pages
364 createScDoc("ods/tdf121716_EvenHeaderFooter.ods");
366 save("Calc Office Open XML");
367 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
368 CPPUNIT_ASSERT(pDoc
);
370 assertXPath(pDoc
, "/x:worksheet/x:headerFooter"_ostr
, "differentOddEven"_ostr
, "true");
371 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddHeader"_ostr
,
372 "&Lodd/right&Cpage&Rheader");
373 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddFooter"_ostr
,
374 "&Lboth&C&12page&Rfooter");
375 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:evenHeader"_ostr
,
376 "&Lpage&Cheader&Reven/left");
377 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:evenFooter"_ostr
,
378 "&Lboth&C&12page&Rfooter");
380 pDoc
= parseExport("xl/worksheets/sheet2.xml");
381 CPPUNIT_ASSERT(pDoc
);
383 assertXPath(pDoc
, "/x:worksheet/x:headerFooter"_ostr
, "differentOddEven"_ostr
, "true");
384 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddHeader"_ostr
, "&Coddh");
385 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddFooter"_ostr
, "&Coddf");
386 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:evenHeader"_ostr
, "&Cevenh");
387 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:evenFooter"_ostr
, "&Levenf");
390 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf134459_HeaderFooterColorXLSX
)
392 // Colors in header and footer should be exported, and imported properly
393 createScDoc("xlsx/tdf134459_HeaderFooterColor.xlsx");
395 save("Calc Office Open XML");
396 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
397 CPPUNIT_ASSERT(pDoc
);
399 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddHeader"_ostr
,
400 "&L&Kc06040l&C&K4c3789c&Rr");
401 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddFooter"_ostr
,
402 "&Ll&C&K64cf5fc&R&Kcd15aar");
405 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf134817_HeaderFooterTextWith2SectionXLSX
)
407 // Header/footer text with multiple selection should be exported, and imported properly
408 createScDoc("xlsx/tdf134817_HeaderFooterTextWith2Section.xlsx");
410 save("Calc Office Open XML");
411 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
412 CPPUNIT_ASSERT(pDoc
);
414 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddHeader"_ostr
,
415 "&L&\"Abadi,Regular\"&11aaa&\"Bembo,Regular\"&20bbb");
416 assertXPathContent(pDoc
, "/x:worksheet/x:headerFooter/x:oddFooter"_ostr
,
417 "&R&\"Cambria,Regular\"&14camb&\"Dante,Regular\"&18dant");
420 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf121718_UseFirstPageNumberXLSX
)
422 // If "First page number" is not checked then useFirstPageNumb, and firstPageNumber should not be exported.
423 createScDoc("ods/tdf121718_UseFirstPageNumber.ods");
425 save("Calc Office Open XML");
426 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
427 CPPUNIT_ASSERT(pDoc
);
429 assertXPath(pDoc
, "/x:worksheet/x:pageSetup"_ostr
, "useFirstPageNumber"_ostr
, "true");
430 assertXPath(pDoc
, "/x:worksheet/x:pageSetup"_ostr
, "firstPageNumber"_ostr
, "10");
432 pDoc
= parseExport("xl/worksheets/sheet2.xml");
433 CPPUNIT_ASSERT(pDoc
);
435 assertXPathNoAttribute(pDoc
, "/x:worksheet/x:pageSetup"_ostr
, "useFirstPageNumber"_ostr
);
436 assertXPathNoAttribute(pDoc
, "/x:worksheet/x:pageSetup"_ostr
, "firstPageNumber"_ostr
);
439 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testHeaderFontStyleXLSX
)
441 createScDoc("xlsx/tdf134826.xlsx");
443 ScDocument
* pDoc
= getScDoc();
444 SfxStyleSheetBase
* pStyleSheet
445 = pDoc
->GetStyleSheetPool()->Find(pDoc
->GetPageStyle(0), SfxStyleFamily::Page
);
446 const SfxItemSet
& rItemSet
= pStyleSheet
->GetItemSet();
447 const ScPageHFItem
& rHFItem
= rItemSet
.Get(ATTR_PAGE_HEADERRIGHT
);
448 const EditTextObject
* pTextObj
= rHFItem
.GetLeftArea();
450 std::vector
<EECharAttrib
> rLst
;
452 // first line is bold.
453 pTextObj
->GetCharAttribs(0, rLst
);
454 bool bHasBold
= std::any_of(rLst
.begin(), rLst
.end(), [](const EECharAttrib
& rAttrib
) {
455 return rAttrib
.pAttr
->Which() == EE_CHAR_WEIGHT
456 && static_cast<const SvxWeightItem
&>(*rAttrib
.pAttr
).GetWeight() == WEIGHT_BOLD
;
458 CPPUNIT_ASSERT_MESSAGE("First line should be bold.", bHasBold
);
460 // second line is italic.
461 pTextObj
->GetCharAttribs(1, rLst
);
462 bool bHasItalic
= std::any_of(rLst
.begin(), rLst
.end(), [](const EECharAttrib
& rAttrib
) {
463 return rAttrib
.pAttr
->Which() == EE_CHAR_ITALIC
464 && static_cast<const SvxPostureItem
&>(*rAttrib
.pAttr
).GetPosture() == ITALIC_NORMAL
;
466 CPPUNIT_ASSERT_MESSAGE("Second line should be italic.", bHasItalic
);
469 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf154445_unused_pagestyles
)
471 createScDoc("ods/tdf108188_pagestyle.ods");
473 // Check if the user defined page style is present
474 constexpr OUString aTestPageStyle
= u
"TestPageStyle"_ustr
;
475 ScDocument
* pDoc
= getScDoc();
476 CPPUNIT_ASSERT_EQUAL(aTestPageStyle
, pDoc
->GetPageStyle(0));
478 // Change page style to default so the user defined one is not used anymore
479 pDoc
->SetPageStyle(0, ScResId(STR_STYLENAME_STANDARD
));
481 // Save and reload the document to check if the unused page styles are still present
482 saveAndReload("calc8");
485 // Without the accompanying fix in place, the unused page styles don't exist anymore
486 ScStyleSheetPool
* pStylePool
= pDoc
->GetStyleSheetPool();
487 CPPUNIT_ASSERT(pStylePool
->Find(aTestPageStyle
, SfxStyleFamily::Page
));
490 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf135828_Shape_Rect
)
494 // tdf#135828 Check that the width and the height of rectangle of the shape is correct.
495 // tdf#123613 Check the positioning, and allow massive rounding errors because of the back and
496 // forth conversion between emu and hmm.
497 createScDoc("xlsx/tdf135828_Shape_Rect.xlsx");
499 save("Calc Office Open XML");
501 xmlDocUniquePtr pDrawing
= parseExport("xl/drawings/drawing1.xml");
502 CPPUNIT_ASSERT(pDrawing
);
504 double nXPosOfTopleft
505 = getXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:off"_ostr
,
508 double nYPosOfTopleft
509 = getXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:off"_ostr
,
513 = getXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:ext"_ostr
,
517 = getXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:spPr/a:xfrm/a:ext"_ostr
,
521 CPPUNIT_ASSERT_DOUBLES_EQUAL(854640, nXPosOfTopleft
, 10000);
522 CPPUNIT_ASSERT_DOUBLES_EQUAL(-570600, nYPosOfTopleft
, 10000);
523 CPPUNIT_ASSERT_DOUBLES_EQUAL(294840, nWidth
, 10000);
524 CPPUNIT_ASSERT_DOUBLES_EQUAL(1988280, nHeight
, 10000);
527 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf123139XLSX
)
529 createScDoc("xlsx/tdf123139_applyAlignment.xlsx");
531 ScDocument
* pDoc
= getScDoc();
532 const ScPatternAttr
* pAttr
= pDoc
->GetPattern(0, 0, 0); //A1
535 const SvxHorJustifyItem
& rJustify
= pAttr
->GetItem(ATTR_HOR_JUSTIFY
);
536 CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Repeat
, rJustify
.GetValue());
539 pAttr
= pDoc
->GetPattern(0, 1, 0); //A2
542 const SfxPoolItem
& rItem
= pAttr
->GetItem(ATTR_HOR_JUSTIFY
);
543 const SvxHorJustifyItem
& rJustify
= static_cast<const SvxHorJustifyItem
&>(rItem
);
544 CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Center
, rJustify
.GetValue());
548 const ScProtectionAttr
& rItem
= pAttr
->GetItem(ATTR_PROTECTION
);
549 CPPUNIT_ASSERT(rItem
.GetProtection());
550 CPPUNIT_ASSERT(!rItem
.GetHideFormula());
553 pAttr
= pDoc
->GetPattern(2, 0, 0); //C1
556 const SfxPoolItem
& rItem
= pAttr
->GetItem(ATTR_HOR_JUSTIFY
);
557 const SvxHorJustifyItem
& rJustify
= static_cast<const SvxHorJustifyItem
&>(rItem
);
558 CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Standard
, rJustify
.GetValue());
562 const ScProtectionAttr
& rItem
= pAttr
->GetItem(ATTR_PROTECTION
);
563 CPPUNIT_ASSERT(rItem
.GetProtection());
564 CPPUNIT_ASSERT(rItem
.GetHideFormula());
567 pAttr
= pDoc
->GetPattern(2, 1, 0); //C2
570 const SfxPoolItem
& rItem
= pAttr
->GetItem(ATTR_HOR_JUSTIFY
);
571 const SvxHorJustifyItem
& rJustify
= static_cast<const SvxHorJustifyItem
&>(rItem
);
572 CPPUNIT_ASSERT_EQUAL(SvxCellHorJustify::Block
, rJustify
.GetValue());
576 const ScProtectionAttr
& rItem
= pAttr
->GetItem(ATTR_PROTECTION
);
577 CPPUNIT_ASSERT(!rItem
.GetProtection());
578 CPPUNIT_ASSERT(!rItem
.GetHideFormula());
582 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf123353
)
584 createScDoc("xlsx/tdf123353.xlsx");
586 save("Calc Office Open XML");
588 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
589 CPPUNIT_ASSERT(pDoc
);
591 assertXPath(pDoc
, "/x:worksheet/x:autoFilter/x:filterColumn/x:filters"_ostr
, "blank"_ostr
, "1");
594 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf140098
)
596 createScDoc("ods/tdf140098.ods");
598 save("Calc Office Open XML");
600 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
601 CPPUNIT_ASSERT(pDoc
);
603 assertXPath(pDoc
, "/x:worksheet/x:autoFilter/x:filterColumn/x:filters"_ostr
, "blank"_ostr
, "1");
606 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf133688_precedents
)
608 // tdf#133688 Check that we do not export detective shapes.
609 createScDoc("ods/tdf133688_dont_save_precedents_to_xlsx.ods");
611 save("Calc Office Open XML");
612 xmlDocUniquePtr pDrawing
= parseExport("xl/drawings/drawing1.xml");
613 CPPUNIT_ASSERT(pDrawing
);
615 // We do not export any shapes.
616 assertXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor[1]"_ostr
, 0);
619 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf91251_missingOverflowRoundtrip
)
621 // tdf#91251 check whether textBox overflow property (horzOverflow and vertOverflow) is
622 // getting preserved after roundtrip
623 createScDoc("xlsx/tdf91251_missingOverflowRoundtrip.xlsx");
625 save("Calc Office Open XML");
627 xmlDocUniquePtr pDrawing
= parseExport("xl/drawings/drawing1.xml");
628 CPPUNIT_ASSERT(pDrawing
);
630 assertXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr"_ostr
,
631 "horzOverflow"_ostr
, "clip");
632 assertXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr"_ostr
,
633 "horzOverflow"_ostr
, "clip");
636 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf137000_handle_upright
)
638 // Upright is an xml attribute of xdr:txBody/a:bodyPr. It is set when in a textbox menu we
639 // choose, 'do not rotate this element'. Implementations are in tdf#106197 with followup
640 // tdf#137000. tdf#149538, tdf#149551 improve the implementation to export 'upright' instead
641 // of workaround 'rot'.
642 createScDoc("xlsx/tdf137000_export_upright.xlsx");
644 save("Calc Office Open XML");
645 xmlDocUniquePtr pDrawing
= parseExport("xl/drawings/drawing1.xml");
646 CPPUNIT_ASSERT(pDrawing
);
648 assertXPath(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:sp/xdr:txBody/a:bodyPr"_ostr
,
649 "upright"_ostr
, "1");
652 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf126305_DataValidatyErrorAlert
)
654 createScDoc("ods/tdf126305.ods");
656 save("Calc Office Open XML");
657 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
658 CPPUNIT_ASSERT(pDoc
);
660 assertXPath(pDoc
, "/x:worksheet/x:dataValidations/x:dataValidation[1]"_ostr
, "errorStyle"_ostr
,
662 assertXPath(pDoc
, "/x:worksheet/x:dataValidations/x:dataValidation[2]"_ostr
, "errorStyle"_ostr
,
664 assertXPath(pDoc
, "/x:worksheet/x:dataValidations/x:dataValidation[3]"_ostr
, "errorStyle"_ostr
,
668 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf76047_externalLink
)
670 createScDoc("xlsx/tdf76047_externalLink.xlsx");
672 // load data from external links. (tdf76047_externalLinkSource.ods)
673 // that file has to be in the same directory as tdf76047_externalLink.xlsx
674 ScDocShell
* pDocSh
= getScDocShell();
675 pDocSh
->ReloadAllLinks();
676 ScDocument
* pDoc
= getScDoc();
678 // compare the data loaded from external links with the expected result stored in the test file
679 for (int nCol
= 1; nCol
<= 5; nCol
++)
681 for (int nRow
= 3; nRow
<= 5; nRow
++)
683 OUString aStr1
= pDoc
->GetString(ScAddress(nCol
, nRow
, 0));
684 OUString aStr2
= pDoc
->GetString(ScAddress(nCol
, nRow
+ 5, 0));
685 OUString aStr3
= pDoc
->GetString(ScAddress(nCol
, nRow
+ 11, 0));
687 CPPUNIT_ASSERT_EQUAL(aStr1
, aStr3
);
688 CPPUNIT_ASSERT_EQUAL(aStr2
, aStr3
);
693 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf87973_externalLinkSkipUnuseds
)
695 createScDoc("ods/tdf87973_externalLinkSkipUnuseds.ods");
697 // try to load data from external link: tdf132105_external.ods
698 // that file has to be in the same directory as tdf87973_externalLinkSkipUnuseds.ods
699 ScDocShell
* pDocSh
= getScDocShell();
700 pDocSh
->ReloadAllLinks();
701 ScDocument
* pDoc
= getScDoc();
703 // change external link to: 87973_externalSource.ods
704 OUString aFormula
= pDoc
->GetFormula(3, 1, 0);
705 auto nIdxOfFilename
= aFormula
.indexOf("tdf132105_external.ods");
706 aFormula
= aFormula
.replaceAt(nIdxOfFilename
, 22, u
"87973_externalSource.ods");
707 auto nIdxOfFile
= aFormula
.indexOf("file");
709 // saveAndReload save the file to a temporary directory
710 // the link must be changed to point to that directory
711 OUString aTempFilename
= utl::CreateTempURL();
712 auto nIdxOfTmpFile
= aTempFilename
.lastIndexOf('/');
713 aTempFilename
= aTempFilename
.copy(0, nIdxOfTmpFile
+ 1);
715 aFormula
= aFormula
.replaceAt(nIdxOfFile
, nIdxOfFilename
- nIdxOfFile
, aTempFilename
);
716 pDoc
->SetFormula(ScAddress(3, 1, 0), aFormula
, formula::FormulaGrammar::GRAM_NATIVE_UI
);
718 // tdf#138832: test the same thing with singleref link
719 aFormula
= pDoc
->GetFormula(3, 2, 0);
720 nIdxOfFilename
= aFormula
.indexOf("tdf132105_external.ods");
721 aFormula
= aFormula
.replaceAt(nIdxOfFilename
, 22, u
"87973_externalSource.ods");
722 nIdxOfFile
= aFormula
.indexOf("file");
724 aFormula
= aFormula
.replaceAt(nIdxOfFile
, nIdxOfFilename
- nIdxOfFile
, aTempFilename
);
725 pDoc
->SetFormula(ScAddress(3, 2, 0), aFormula
, formula::FormulaGrammar::GRAM_NATIVE_UI
);
727 // save and load back
728 saveAndReload("Calc Office Open XML");
730 // check if the new filename is present in the link (and not replaced by '[2]')
732 OUString aFormula2
= pDoc
->GetFormula(3, 1, 0);
733 CPPUNIT_ASSERT(aFormula2
.indexOf("tdf132105_external.ods") < 0);
734 CPPUNIT_ASSERT(aFormula2
.indexOf("87973_externalSource.ods") >= 0);
735 aFormula2
= pDoc
->GetFormula(3, 2, 0);
736 CPPUNIT_ASSERT(aFormula2
.indexOf("tdf132105_external.ods") < 0);
737 CPPUNIT_ASSERT(aFormula2
.indexOf("87973_externalSource.ods") >= 0);
740 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf51022_lostPrintRange
)
742 createScDoc("ods/tdf87973_externalLinkSkipUnuseds.ods");
744 ScDocShell
* pDocSh
= getScDocShell();
745 pDocSh
->ReloadAllLinks();
746 ScDocument
* pDoc
= getScDoc();
749 ScRange
aRange1(1, 2, 0, 3, 4, 0);
750 ScRange
aRange2(1, 6, 0, 3, 7, 0);
751 pDoc
->AddPrintRange(0, aRange1
);
752 pDoc
->AddPrintRange(0, aRange2
);
754 // save and load back
755 saveAndReload("calc8");
757 // check if the same print ranges are present
759 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(2), pDoc
->GetPrintRangeCount(0));
760 CPPUNIT_ASSERT_EQUAL(aRange1
, *pDoc
->GetPrintRange(0, 0));
761 CPPUNIT_ASSERT_EQUAL(aRange2
, *pDoc
->GetPrintRange(0, 1));
764 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf138741_externalLinkSkipUnusedsCrash
)
766 createScDoc("xlsx/tdf138741_externalLinkSkipUnusedsCrash.xlsx");
768 //without the fix in place, it would have crashed at export time
769 save("Calc Office Open XML");
772 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf138824_linkToParentDirectory
)
774 createScDoc("ods/childDir/tdf138824_linkToParentDirectory.ods");
776 ScDocument
* pDoc
= getScDoc();
778 // saveAndReload save the file to a temporary directory
779 // the link must be changed to point to that parent directory
780 OUString aTempFilename
= utl::CreateTempURL();
781 auto nIdxOfTmpFile
= aTempFilename
.lastIndexOf('/');
782 nIdxOfTmpFile
= aTempFilename
.lastIndexOf('/', nIdxOfTmpFile
);
783 aTempFilename
= aTempFilename
.copy(0, nIdxOfTmpFile
+ 1);
785 // change external link to tmp directory
786 OUString aFormula
= pDoc
->GetFormula(3, 1, 0);
787 auto nIdxOfFilename
= aFormula
.indexOf("tdf138824_externalSource.ods");
788 auto nIdxOfFile
= aFormula
.indexOf("file");
790 aFormula
= aFormula
.replaceAt(nIdxOfFile
, nIdxOfFilename
- nIdxOfFile
, aTempFilename
);
791 pDoc
->SetFormula(ScAddress(3, 1, 0), aFormula
, formula::FormulaGrammar::GRAM_NATIVE_UI
);
793 save("Calc Office Open XML");
794 xmlDocUniquePtr pDocXml
= parseExport("xl/externalLinks/_rels/externalLink1.xml.rels");
795 CPPUNIT_ASSERT(pDocXml
);
797 // test also the Linux specific bug tdf#121472
798 assertXPath(pDocXml
, "/rels:Relationships/rels:Relationship"_ostr
, "Target"_ostr
,
799 "../tdf138824_externalSource.ods");
802 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf129969
)
804 createScDoc("ods/external_hyperlink.ods");
806 saveAndReload("Calc Office Open XML");
807 ScDocument
* pDoc
= getScDoc();
808 ScAddress
aPos(0, 0, 0);
809 const EditTextObject
* pEditText
= pDoc
->GetEditText(aPos
);
810 const SvxFieldData
* pData
= pEditText
->GetFieldData(0, 0, text::textfield::Type::URL
);
811 const SvxURLField
* pURLData
= static_cast<const SvxURLField
*>(pData
);
812 CPPUNIT_ASSERT(pURLData
->GetURL().endsWith("/%23folder/test.ods#Sheet2.B10"));
815 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf147088
)
817 createScDoc("fods/tdf147088.fods");
819 saveAndReload("Calc Office Open XML");
821 ScDocument
* pDoc
= getScDoc();
823 // Without the fix in place, this test would have failed with
824 // - Expected: _xffff_
826 CPPUNIT_ASSERT_EQUAL(OUString("_xffff_"), pDoc
->GetString(0, 0, 0));
829 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf84874
)
831 createScDoc("ods/tdf84874.ods");
833 saveAndReload("Calc Office Open XML");
835 ScDocument
* pDoc
= getScDoc();
837 const ScValidationData
* pData
= pDoc
->GetValidationEntry(1);
838 OUString aTitle
, aText
;
839 pData
->GetInput(aTitle
, aText
);
840 sal_uInt32 nPromptTitleLen
= aTitle
.getLength();
841 sal_uInt32 nPromptTextLen
= aText
.getLength();
843 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(255), nPromptTitleLen
);
844 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(255), nPromptTextLen
);
846 ScValidErrorStyle eErrStyle
= SC_VALERR_STOP
;
847 pData
->GetErrMsg(aTitle
, aText
, eErrStyle
);
848 sal_uInt32 nErrorTitleLen
= aTitle
.getLength();
849 sal_uInt32 nErrorTextLen
= aText
.getLength();
851 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(255), nErrorTitleLen
);
852 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32
>(255), nErrorTextLen
);
855 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf136721_paper_size
)
857 createScDoc("xlsx/tdf136721_letter_sized_paper.xlsx");
859 save("Calc Office Open XML");
860 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
861 CPPUNIT_ASSERT(pDoc
);
863 assertXPath(pDoc
, "/x:worksheet/x:pageSetup"_ostr
, "paperSize"_ostr
, "70");
866 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf139258_rotated_image
)
868 // Check that the topleft position of the image is correct.
869 createScDoc("ods/tdf139258_rotated_image.ods");
871 save("Calc Office Open XML");
873 xmlDocUniquePtr pDrawing
= parseExport("xl/drawings/drawing1.xml");
874 CPPUNIT_ASSERT(pDrawing
);
876 assertXPathContent(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:from/xdr:col"_ostr
, "1");
877 assertXPathContent(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:from/xdr:row"_ostr
, "12");
878 assertXPathContent(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:to/xdr:col"_ostr
, "6");
879 assertXPathContent(pDrawing
, "/xdr:wsDr/xdr:twoCellAnchor/xdr:to/xdr:row"_ostr
, "25");
882 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf144642_RowHeightRounding
)
884 // MS Excel round down row heights to 0.75pt
885 // MS Excel can save a row height of 28.35pt, but will display it as a row height of 27.75pt.
886 // Calc simulates this roundings but only if the xlsx file was saved in MS Excel.
888 createScDoc("xlsx/tdf144642_RowHeight_10mm_SavedByCalc.xlsx");
889 ScDocument
* pDoc
= getScDoc();
890 // 10mm == 567 twips == 28.35pt
891 CPPUNIT_ASSERT_EQUAL(sal_uInt16(567), pDoc
->GetRowHeight(0, 0));
892 CPPUNIT_ASSERT_EQUAL(tools::Long(567 * 26), pDoc
->GetRowHeight(0, 25, 0, true));
894 createScDoc("xlsx/tdf144642_RowHeight_28.35pt_SavedByExcel.xlsx");
896 // 555twips == 27.75pt == 9.79mm
897 CPPUNIT_ASSERT_EQUAL(sal_uInt16(555), pDoc
->GetRowHeight(0, 0));
898 CPPUNIT_ASSERT_EQUAL(tools::Long(555 * 26), pDoc
->GetRowHeight(0, 25, 0, true));
901 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf145129_DefaultRowHeightRounding
)
903 // MS Excel round down row heights to 0.75pt
904 // Same as Tdf144642 but with default row height.
906 createScDoc("xlsx/tdf145129_DefaultRowHeight_28.35pt_SavedByExcel.xlsx");
907 ScDocument
* pDoc
= getScDoc();
908 // 555twips == 27.75pt == 9.79mm
909 CPPUNIT_ASSERT_EQUAL(sal_uInt16(555), pDoc
->GetRowHeight(0, 0));
910 CPPUNIT_ASSERT_EQUAL(tools::Long(555 * 52), pDoc
->GetRowHeight(0, 51, 0, true));
913 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf151755_stylesLostOnXLSXExport
)
915 // Check if empty cells with custom style are exported, even if
916 // there is other empty cells with default style, left of it.
917 createScDoc("xlsx/tdf151755_stylesLostOnXLSXExport.xlsx");
919 // Resave the xlsx file without any modification.
920 save("Calc Office Open XML");
921 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
922 CPPUNIT_ASSERT(pSheet
);
924 // Check if all the 3 empty cells with styles are saved, and have the same style id.
925 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]/x:c"_ostr
, 4);
926 OUString aCellStyleId
927 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]/x:c[2]"_ostr
, "s"_ostr
);
928 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]/x:c[2]"_ostr
, "s"_ostr
, aCellStyleId
);
929 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]/x:c[3]"_ostr
, "s"_ostr
, aCellStyleId
);
930 assertXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[4]/x:c[4]"_ostr
, "s"_ostr
, aCellStyleId
);
933 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf152581_bordercolorNotExportedToXLSX
)
935 createScDoc("xlsx/tdf152581_bordercolorNotExportedToXLSX.xlsx");
937 // Resave the xlsx file without any modification.
938 save("Calc Office Open XML");
939 xmlDocUniquePtr pStyles
= parseExport("xl/styles.xml");
940 CPPUNIT_ASSERT(pStyles
);
942 // Check if conditional format border color is exported
943 assertXPath(pStyles
, "/x:styleSheet/x:dxfs/x:dxf/x:border/x:left/x:color"_ostr
, "theme"_ostr
,
947 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf140431
)
949 createScDoc("xlsx/129969-min.xlsx");
951 saveAndReload("Calc Office Open XML");
952 ScDocument
* pDoc
= getScDoc();
953 ScAddress
aPos(0, 2, 0);
954 const EditTextObject
* pEditText
= pDoc
->GetEditText(aPos
);
955 const SvxFieldData
* pData
= pEditText
->GetFieldData(0, 0, text::textfield::Type::URL
);
956 const SvxURLField
* pURLData
= static_cast<const SvxURLField
*>(pData
);
957 CPPUNIT_ASSERT(pURLData
->GetURL().startsWith("file://ndhlis"));
960 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testCheckboxFormControlXlsxExport
)
964 // Given a document that has a checkbox form control:
965 createScDoc("xlsx/checkbox-form-control.xlsx");
967 // When exporting to XLSX:
968 save("Calc Office Open XML");
970 // Then make sure its VML markup is written and it has a correct position + size:
971 xmlDocUniquePtr pDoc
= parseExport("xl/drawings/vmlDrawing1.vml");
972 // Without the fix in place, this test would have failed as there was no such stream.
973 CPPUNIT_ASSERT(pDoc
);
974 assertXPathContent(pDoc
, "/xml/v:shape/xx:ClientData/xx:Anchor"_ostr
,
975 "1, 22, 3, 3, 3, 30, 6, 1");
978 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testButtonFormControlXlsxExport
)
980 // Given a document that has a checkbox form control:
981 createScDoc("xlsx/button-form-control.xlsx");
983 // When exporting to XLSX:
984 save("Calc Office Open XML");
986 // Then make sure its control markup is written and it has a correct position + size:
987 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
988 CPPUNIT_ASSERT(pDoc
);
989 // Without the fix in place, this test would have failed with:
990 // - XPath '//x:anchor/x:from/xdr:col' not found
991 // i.e. the control markup was missing, the button was lost on export.
992 assertXPathContent(pDoc
, "//x:anchor/x:from/xdr:col"_ostr
, "1");
993 assertXPathContent(pDoc
, "//x:anchor/x:from/xdr:row"_ostr
, "3");
994 assertXPathContent(pDoc
, "//x:anchor/x:to/xdr:col"_ostr
, "3");
995 assertXPathContent(pDoc
, "//x:anchor/x:to/xdr:row"_ostr
, "7");
997 // Also make sure that an empty macro attribute is not written.
998 // Without the fix in place, this test would have failed with:
999 // - XPath '//x:controlPr' unexpected 'macro' attribute
1000 // i.e. macro in an xlsx file was not omitted, which is considered invalid by Excel.
1001 assertXPathNoAttribute(pDoc
, "//x:controlPr"_ostr
, "macro"_ostr
);
1004 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf142929_filterLessThanXLSX
)
1006 // Document contains a standard filter with '<' condition.
1007 createScDoc("xlsx/tdf142929.xlsx");
1009 save("Calc Office Open XML");
1010 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
1011 CPPUNIT_ASSERT(pDoc
);
1012 assertXPath(pDoc
, "//x:customFilters/x:customFilter"_ostr
, "val"_ostr
, "2");
1013 assertXPath(pDoc
, "//x:customFilters/x:customFilter"_ostr
, "operator"_ostr
, "lessThan");
1016 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testInvalidNamedRange
)
1018 // Given a document which has a named range (myname) that refers to the "1" external link, but
1019 // the link's type is xlPathMissing, when importing that document:
1020 createScDoc("xlsx/invalid-named-range.xlsx");
1022 // Then make sure that named range is ignored, as "1" can't be resolved, and exporting it back
1023 // to XLSX (without the xlPathMissing link) would corrupt the document:
1024 uno::Reference
<beans::XPropertySet
> xDocProps(mxComponent
, uno::UNO_QUERY
);
1025 uno::Reference
<container::XNameAccess
> xNamedRanges(xDocProps
->getPropertyValue("NamedRanges"),
1027 // Without the fix in place, this test would have failed, we didn't ignore the problematic named
1029 CPPUNIT_ASSERT(!xNamedRanges
->hasByName("myname"));
1032 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testExternalDefinedNameXLSX
)
1034 createScDoc("xlsx/tdf144397.xlsx");
1035 saveAndReload("Calc Office Open XML");
1037 ScDocShell
* pDocSh
= getScDocShell();
1038 pDocSh
->ReloadAllLinks();
1039 ScDocument
* pDoc
= getScDoc();
1044 const ScFormulaCell
* pFC
= pDoc
->GetFormulaCell(ScAddress(1, 1, 0));
1045 sc::FormulaResultValue aRes
= pFC
->GetResult();
1046 CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::String
, aRes
.meType
);
1047 CPPUNIT_ASSERT_EQUAL(OUString("January"), aRes
.maString
.getString());
1051 const ScFormulaCell
* pFC
= pDoc
->GetFormulaCell(ScAddress(1, 3, 0));
1052 sc::FormulaResultValue aRes
= pFC
->GetResult();
1053 CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::String
, aRes
.meType
);
1054 CPPUNIT_ASSERT_EQUAL(OUString("March"), aRes
.maString
.getString());
1058 const ScFormulaCell
* pFC
= pDoc
->GetFormulaCell(ScAddress(1, 5, 0));
1059 sc::FormulaResultValue aRes
= pFC
->GetResult();
1060 CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::Error
, aRes
.meType
);
1061 CPPUNIT_ASSERT_EQUAL(OUString(""), aRes
.maString
.getString());
1065 const ScFormulaCell
* pFC
= pDoc
->GetFormulaCell(ScAddress(1, 6, 0));
1066 sc::FormulaResultValue aRes
= pFC
->GetResult();
1067 CPPUNIT_ASSERT_EQUAL(sc::FormulaResultValue::String
, aRes
.meType
);
1068 CPPUNIT_ASSERT_EQUAL(OUString("June"), aRes
.maString
.getString());
1071 save("Calc Office Open XML");
1072 xmlDocUniquePtr pDocXml
= parseExport("xl/externalLinks/externalLink1.xml");
1074 CPPUNIT_ASSERT(pDocXml
);
1075 assertXPath(pDocXml
, "/x:externalLink/x:externalBook/x:sheetNames/x:sheetName"_ostr
, "val"_ostr
,
1077 assertXPath(pDocXml
, "/x:externalLink/x:externalBook/x:definedNames/x:definedName"_ostr
,
1078 "name"_ostr
, "MonthNames");
1079 // TODO: no need for the [1] external document identifier
1080 assertXPath(pDocXml
, "/x:externalLink/x:externalBook/x:definedNames/x:definedName"_ostr
,
1081 "refersTo"_ostr
, "[1]Munka1!$A$2:$A$13");
1082 assertXPath(pDocXml
, "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData"_ostr
,
1083 "sheetId"_ostr
, "0");
1084 assertXPath(pDocXml
, "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData/x:row[2]"_ostr
,
1088 "/x:externalLink/x:externalBook/x:sheetDataSet/x:sheetData/x:row[2]/x:cell/x:v"_ostr
,
1092 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testHyperlinkLocationXLSX
)
1094 createScDoc("ods/tdf143220.ods");
1096 save("Calc Office Open XML");
1097 xmlDocUniquePtr pDoc
= parseExport("xl/worksheets/sheet1.xml");
1098 CPPUNIT_ASSERT(pDoc
);
1100 // tdf#143220 link to sheet not valid without cell reference
1101 assertXPath(pDoc
, "/x:worksheet/x:hyperlinks/x:hyperlink[@ref='A1']"_ostr
, "location"_ostr
,
1104 // tdf#145079 link with defined name target didn't work because Calc added "A1" at the end
1105 assertXPath(pDoc
, "/x:worksheet/x:hyperlinks/x:hyperlink[@ref='A2']"_ostr
, "location"_ostr
,
1107 assertXPath(pDoc
, "/x:worksheet/x:hyperlinks/x:hyperlink[@ref='A3']"_ostr
, "location"_ostr
,
1111 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf142264ManyChartsToXLSX
)
1113 // The cache size for the test should be small enough, to make sure that some charts get
1114 // unloaded in the process, and then loaded on demand properly (default is currently 200)
1115 comphelper::ScopeGuard
g([]() {
1116 std::shared_ptr
<comphelper::ConfigurationChanges
> pBatch(
1117 comphelper::ConfigurationChanges::create());
1118 officecfg::Office::Common::Cache::DrawingEngine::OLE_Objects::set(200, pBatch
);
1119 return pBatch
->commit();
1121 std::shared_ptr
<comphelper::ConfigurationChanges
> pBatch(
1122 comphelper::ConfigurationChanges::create());
1123 officecfg::Office::Common::Cache::DrawingEngine::OLE_Objects::set(20, pBatch
);
1126 createScDoc("ods/many_charts.ods");
1127 saveAndReload("Calc Office Open XML");
1129 css::uno::Reference
<css::drawing::XDrawPagesSupplier
> xSupplier(mxComponent
,
1130 css::uno::UNO_QUERY_THROW
);
1131 auto xDrawPages
= xSupplier
->getDrawPages();
1133 // No charts (or other objects) on the first sheet, and resp. first draw page
1134 css::uno::Reference
<css::drawing::XDrawPage
> xPage(xDrawPages
->getByIndex(0),
1135 css::uno::UNO_QUERY_THROW
);
1136 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPage
->getCount());
1138 // 20 charts on the second sheet, and resp. second draw page
1139 xPage
.set(xDrawPages
->getByIndex(1), css::uno::UNO_QUERY_THROW
);
1140 // Without the fix in place, this test would have failed with
1143 // Because only the last 20 charts would get exported, all on the third sheet
1144 CPPUNIT_ASSERT_EQUAL(sal_Int32(20), xPage
->getCount());
1145 for (sal_Int32 i
= 0; i
< xPage
->getCount(); ++i
)
1147 css::uno::Reference
<css::beans::XPropertySet
> xProps(xPage
->getByIndex(i
),
1148 css::uno::UNO_QUERY_THROW
);
1149 css::uno::Reference
<css::chart2::XChartDocument
> xChart(xProps
->getPropertyValue("Model"),
1150 css::uno::UNO_QUERY_THROW
);
1151 const auto xDiagram
= xChart
->getFirstDiagram();
1152 CPPUNIT_ASSERT(xDiagram
);
1154 css::uno::Reference
<css::chart2::XCoordinateSystemContainer
> xCooSysContainer(
1155 xDiagram
, uno::UNO_QUERY_THROW
);
1157 const auto xCooSysSeq
= xCooSysContainer
->getCoordinateSystems();
1158 for (const auto& rCooSys
: xCooSysSeq
)
1160 css::uno::Reference
<css::chart2::XChartTypeContainer
> xChartTypeCont(
1161 rCooSys
, uno::UNO_QUERY_THROW
);
1162 uno::Sequence
<uno::Reference
<chart2::XChartType
>> xChartTypeSeq
1163 = xChartTypeCont
->getChartTypes();
1164 CPPUNIT_ASSERT(xChartTypeSeq
.hasElements());
1168 // 20 charts on the third sheet, and resp. third draw page
1169 xPage
.set(xDrawPages
->getByIndex(2), css::uno::UNO_QUERY_THROW
);
1170 CPPUNIT_ASSERT_EQUAL(sal_Int32(20), xPage
->getCount());
1171 for (sal_Int32 i
= 0; i
< xPage
->getCount(); ++i
)
1173 css::uno::Reference
<css::beans::XPropertySet
> xProps(xPage
->getByIndex(i
),
1174 css::uno::UNO_QUERY_THROW
);
1175 css::uno::Reference
<css::chart2::XChartDocument
> xChart(xProps
->getPropertyValue("Model"),
1176 css::uno::UNO_QUERY_THROW
);
1177 const auto xDiagram
= xChart
->getFirstDiagram();
1178 CPPUNIT_ASSERT(xDiagram
);
1180 css::uno::Reference
<css::chart2::XCoordinateSystemContainer
> xCooSysContainer(
1181 xDiagram
, uno::UNO_QUERY_THROW
);
1183 const auto xCooSysSeq
= xCooSysContainer
->getCoordinateSystems();
1184 for (const auto& rCooSys
: xCooSysSeq
)
1186 css::uno::Reference
<css::chart2::XChartTypeContainer
> xChartTypeCont(
1187 rCooSys
, uno::UNO_QUERY_THROW
);
1188 uno::Sequence
<uno::Reference
<chart2::XChartType
>> xChartTypeSeq
1189 = xChartTypeCont
->getChartTypes();
1190 CPPUNIT_ASSERT(xChartTypeSeq
.hasElements());
1195 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf143929MultiColumnToODS
)
1197 createScDoc("ods/two-col-shape.ods");
1200 css::uno::Reference
<css::drawing::XDrawPagesSupplier
> xSupplier(mxComponent
,
1201 css::uno::UNO_QUERY_THROW
);
1202 css::uno::Reference
<css::drawing::XDrawPage
> xPage(xSupplier
->getDrawPages()->getByIndex(0),
1203 css::uno::UNO_QUERY_THROW
);
1204 css::uno::Reference
<css::container::XIndexAccess
> xIndexAccess(xPage
,
1205 css::uno::UNO_QUERY_THROW
);
1206 css::uno::Reference
<css::drawing::XShape
> xShape(xIndexAccess
->getByIndex(0),
1207 css::uno::UNO_QUERY_THROW
);
1208 css::uno::Reference
<css::beans::XPropertySet
> xProps(xShape
, css::uno::UNO_QUERY_THROW
);
1209 css::uno::Reference
<css::text::XTextColumns
> xCols(xProps
->getPropertyValue("TextColumns"),
1210 css::uno::UNO_QUERY_THROW
);
1211 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xCols
->getColumnCount());
1212 css::uno::Reference
<css::beans::XPropertySet
> xColProps(xCols
, css::uno::UNO_QUERY_THROW
);
1213 CPPUNIT_ASSERT_EQUAL(css::uno::Any(sal_Int32(1000)),
1214 xColProps
->getPropertyValue("AutomaticDistance"));
1217 saveAndReload("calc8");
1219 css::uno::Reference
<css::drawing::XDrawPagesSupplier
> xSupplier(mxComponent
,
1220 css::uno::UNO_QUERY_THROW
);
1221 css::uno::Reference
<css::drawing::XDrawPage
> xPage(xSupplier
->getDrawPages()->getByIndex(0),
1222 css::uno::UNO_QUERY_THROW
);
1223 css::uno::Reference
<css::container::XIndexAccess
> xIndexAccess(xPage
,
1224 css::uno::UNO_QUERY_THROW
);
1225 css::uno::Reference
<css::drawing::XShape
> xShape(xIndexAccess
->getByIndex(0),
1226 css::uno::UNO_QUERY_THROW
);
1227 css::uno::Reference
<css::beans::XPropertySet
> xProps(xShape
, css::uno::UNO_QUERY_THROW
);
1229 // Without the fix in place, this would have failed with:
1230 // An uncaught exception of type com.sun.star.uno.RuntimeException
1231 // - unsatisfied query for interface of type com.sun.star.text.XTextColumns!
1232 css::uno::Reference
<css::text::XTextColumns
> xCols(xProps
->getPropertyValue("TextColumns"),
1233 css::uno::UNO_QUERY_THROW
);
1234 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xCols
->getColumnCount());
1235 css::uno::Reference
<css::beans::XPropertySet
> xColProps(xCols
, css::uno::UNO_QUERY_THROW
);
1236 CPPUNIT_ASSERT_EQUAL(css::uno::Any(sal_Int32(1000)),
1237 xColProps
->getPropertyValue("AutomaticDistance"));
1240 xmlDocUniquePtr pXmlDoc
= parseExport("content.xml");
1241 CPPUNIT_ASSERT(pXmlDoc
);
1242 // Without the fix in place, this would have failed with:
1245 // - In <>, XPath '/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/
1246 // style:graphic-properties/style:columns' number of nodes is incorrect
1249 "/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/"
1250 "style:graphic-properties/style:columns"_ostr
,
1251 "column-count"_ostr
, "2");
1252 // Only test that "column-gap" attribute exists, not its value that depends on locale (cm, in)
1255 "/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/"
1256 "style:graphic-properties/style:columns"_ostr
,
1260 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf142578
)
1262 createScDoc("ods/tdf142578.ods");
1264 save("Calc Office Open XML");
1265 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
1266 CPPUNIT_ASSERT(pSheet
);
1268 // Get DxfId for color filter
1269 sal_Int32 nDxfIdColorFilter
1270 = getXPath(pSheet
, "/x:worksheet/x:autoFilter/x:filterColumn/x:colorFilter"_ostr
,
1275 // Get DxfId for conditional formatting
1276 sal_Int32 nDxfIdCondFormat
1277 = getXPath(pSheet
, "/x:worksheet/x:conditionalFormatting/x:cfRule"_ostr
, "dxfId"_ostr
)
1281 // Ensure they are using different dxfs
1282 CPPUNIT_ASSERT_MESSAGE("dxfID's should be different!", nDxfIdColorFilter
!= nDxfIdCondFormat
);
1284 // Check colors used by these dxfs
1285 xmlDocUniquePtr pStyles
= parseExport("xl/styles.xml");
1286 CPPUNIT_ASSERT(pStyles
);
1288 OString
sDxfColorFilterXPath("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfIdColorFilter
)
1289 + "]/x:fill/x:patternFill/x:fgColor");
1290 assertXPath(pStyles
, sDxfColorFilterXPath
, "rgb"_ostr
, "FF81D41A");
1292 OString
sDxfCondFormatXPath("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfIdCondFormat
)
1293 + "]/x:fill/x:patternFill/x:bgColor");
1294 assertXPath(pStyles
, sDxfCondFormatXPath
, "rgb"_ostr
, "FFFFCCCC");
1297 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf145059
)
1299 createScDoc("ods/tdf145059.ods");
1302 save("Calc Office Open XML");
1303 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
1304 CPPUNIT_ASSERT(pSheet
);
1305 xmlDocUniquePtr pStyle
= parseExport("xl/styles.xml");
1306 CPPUNIT_ASSERT(pStyle
);
1308 sal_Int32 nColorFilterDxdId
1309 = getXPath(pSheet
, "/x:worksheet/x:autoFilter/x:filterColumn/x:colorFilter"_ostr
,
1313 // Ensure that dxf id is not -1
1314 CPPUNIT_ASSERT(nColorFilterDxdId
>= 0);
1316 // Find color by this dxfid
1317 OString sDxfIdPath
= "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nColorFilterDxdId
+ 1)
1318 + "]/x:fill/x:patternFill/x:fgColor";
1319 assertXPath(pStyle
, sDxfIdPath
, "rgb"_ostr
, "FF4472C4");
1322 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf130104_XLSXIndent
)
1324 createScDoc("xlsx/tdf130104_indent.xlsx");
1326 // Resave the xlsx file without any modification.
1327 save("Calc Office Open XML");
1328 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
1329 CPPUNIT_ASSERT(pSheet
);
1330 xmlDocUniquePtr pStyle
= parseExport("xl/styles.xml");
1331 CPPUNIT_ASSERT(pStyle
);
1333 // Check to see whether the indents remain the same as the original ones:
1335 // Get the style index number for cell A1
1336 sal_Int32 nCellA1StyleIndex
1337 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[1]/x:c[1]"_ostr
, "s"_ostr
).toInt32() + 1;
1338 // The indent for cell A1 should be 0
1339 OString sStyleA1XPath
1340 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA1StyleIndex
) + "]/x:alignment";
1341 // (if this assertion fails, you should first check whether there is no style index set for this cell)
1342 assertXPath(pStyle
, sStyleA1XPath
, "indent"_ostr
, "0");
1344 sal_Int32 nCellA3StyleIndex
1345 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[3]/x:c[1]"_ostr
, "s"_ostr
).toInt32() + 1;
1346 // The indent for cell A3 should be 1
1347 OString sStyleA3XPath
1348 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA3StyleIndex
) + "]/x:alignment";
1349 assertXPath(pStyle
, sStyleA3XPath
, "indent"_ostr
, "1");
1351 sal_Int32 nCellA6StyleIndex
1352 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[6]/x:c[1]"_ostr
, "s"_ostr
).toInt32() + 1;
1353 OString sStyleA6XPath
1354 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA6StyleIndex
) + "]/x:alignment";
1355 assertXPath(pStyle
, sStyleA6XPath
, "indent"_ostr
, "2");
1357 sal_Int32 nCellA9StyleIndex
1358 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[9]/x:c[1]"_ostr
, "s"_ostr
).toInt32() + 1;
1359 OString sStyleA9XPath
1360 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA9StyleIndex
) + "]/x:alignment";
1361 assertXPath(pStyle
, sStyleA9XPath
, "indent"_ostr
, "3");
1363 sal_Int32 nCellA12StyleIndex
1364 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[12]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1366 OString sStyleA12XPath
1367 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA12StyleIndex
) + "]/x:alignment";
1368 assertXPath(pStyle
, sStyleA12XPath
, "indent"_ostr
, "4");
1370 sal_Int32 nCellA15StyleIndex
1371 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[15]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1373 OString sStyleA15XPath
1374 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA15StyleIndex
) + "]/x:alignment";
1375 assertXPath(pStyle
, sStyleA15XPath
, "indent"_ostr
, "5");
1377 sal_Int32 nCellA18StyleIndex
1378 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[18]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1380 OString sStyleA18XPath
1381 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA18StyleIndex
) + "]/x:alignment";
1382 assertXPath(pStyle
, sStyleA18XPath
, "indent"_ostr
, "6");
1384 sal_Int32 nCellA21StyleIndex
1385 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[21]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1387 OString sStyleA21XPath
1388 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA21StyleIndex
) + "]/x:alignment";
1389 assertXPath(pStyle
, sStyleA21XPath
, "indent"_ostr
, "7");
1391 sal_Int32 nCellA24StyleIndex
1392 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[24]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1394 OString sStyleA24XPath
1395 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA24StyleIndex
) + "]/x:alignment";
1396 assertXPath(pStyle
, sStyleA24XPath
, "indent"_ostr
, "8");
1398 sal_Int32 nCellA27StyleIndex
1399 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[27]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1401 OString sStyleA27XPath
1402 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA27StyleIndex
) + "]/x:alignment";
1403 assertXPath(pStyle
, sStyleA27XPath
, "indent"_ostr
, "9");
1405 sal_Int32 nCellA30StyleIndex
1406 = getXPath(pSheet
, "/x:worksheet/x:sheetData/x:row[30]/x:c[1]"_ostr
, "s"_ostr
).toInt32()
1408 OString sStyleA30XPath
1409 = "/x:styleSheet/x:cellXfs/x:xf[" + OString::number(nCellA30StyleIndex
) + "]/x:alignment";
1410 assertXPath(pStyle
, sStyleA30XPath
, "indent"_ostr
, "10");
1413 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testWholeRowBold
)
1418 ScDocument
* pDoc
= getScDoc();
1420 // Make entire second row bold.
1421 ScPatternAttr
boldAttr(pDoc
->GetPool());
1422 boldAttr
.GetItemSet().Put(SvxWeightItem(WEIGHT_BOLD
, ATTR_FONT_WEIGHT
));
1423 pDoc
->ApplyPatternAreaTab(0, 1, pDoc
->MaxCol(), 1, 0, boldAttr
);
1426 saveAndReload("calc8");
1427 ScDocument
* pDoc
= getScDoc();
1428 CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT
), pDoc
->GetAllocatedColumnsCount(0));
1430 pDoc
->GetPattern(pDoc
->MaxCol(), 1, 0)->fillFontOnly(aFont
);
1431 CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD
, aFont
.GetWeight());
1433 saveAndReload("Calc Office Open XML");
1435 CPPUNIT_ASSERT_EQUAL(SCCOL(INITIALCOLCOUNT
), pDoc
->GetAllocatedColumnsCount(0));
1436 pDoc
->GetPattern(pDoc
->MaxCol(), 1, 0)->fillFontOnly(aFont
);
1437 CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD
, aFont
.GetWeight());
1440 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testXlsxRowsOrder
)
1442 createScDoc("xlsx/tdf58243.xlsx");
1443 // Make sure code in SheetDataBuffer doesn't assert columns/rows sorting.
1444 save("Calc Office Open XML");
1447 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf91286
)
1449 createScDoc("ods/tdf91286.ods");
1450 save("Calc Office Open XML");
1452 Reference
<packages::zip::XZipFileAccess2
> xNameAccess
1453 = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory
),
1454 maTempFile
.GetURL());
1455 const Sequence
<OUString
> aNames(xNameAccess
->getElementNames());
1456 int nImageFiles
= 0;
1457 for (const auto& rElementName
: aNames
)
1458 if (rElementName
.startsWith("xl/media/image"))
1461 // Without the accompanying fix in place, this test would have failed with:
1464 // i.e. the embedded picture would have been saved twice.
1465 CPPUNIT_ASSERT_EQUAL(1, nImageFiles
);
1468 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf148820
)
1470 createScDoc("xlsx/tdf148820.xlsx");
1471 save("Calc Office Open XML");
1472 xmlDocUniquePtr pSheet
= parseExport("xl/worksheets/sheet1.xml");
1473 CPPUNIT_ASSERT(pSheet
);
1475 sal_Int32 nDxfIdCondFormatFirst
1476 = getXPath(pSheet
, "/x:worksheet/x:conditionalFormatting[1]/x:cfRule"_ostr
, "dxfId"_ostr
)
1479 sal_Int32 nDxfIdCondFormatLast
1480 = getXPath(pSheet
, "/x:worksheet/x:conditionalFormatting[20]/x:cfRule"_ostr
, "dxfId"_ostr
)
1484 xmlDocUniquePtr pStyles
= parseExport("xl/styles.xml");
1485 CPPUNIT_ASSERT(pStyles
);
1487 OString
sDxfCondFormatXPath("/x:styleSheet/x:dxfs/x:dxf["
1488 + OString::number(nDxfIdCondFormatFirst
)
1489 + "]/x:fill/x:patternFill/x:bgColor");
1490 assertXPath(pStyles
, sDxfCondFormatXPath
, "rgb"_ostr
, "FF53B5A9");
1492 = OString("/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nDxfIdCondFormatLast
)
1493 + "]/x:fill/x:patternFill/x:bgColor");
1494 assertXPath(pStyles
, sDxfCondFormatXPath
, "rgb"_ostr
, "FFA30000");
1499 void lcl_TestNumberFormat(ScDocument
& rDoc
, const OUString
& rFormatStrOK
)
1501 sal_uInt32 nNumberFormat
= rDoc
.GetNumberFormat(0, 0, 0);
1502 const SvNumberformat
* pNumberFormat
= rDoc
.GetFormatTable()->GetEntry(nNumberFormat
);
1503 const OUString
& rFormatStr
= pNumberFormat
->GetFormatstring();
1505 CPPUNIT_ASSERT_EQUAL(rFormatStrOK
, rFormatStr
);
1508 void lcl_SetNumberFormat(ScDocument
& rDoc
, const OUString
& rFormat
)
1510 sal_Int32 nCheckPos
;
1511 SvNumFormatType nType
;
1513 OUString aNewFormat
= rFormat
;
1514 SvNumberFormatter
* pFormatter
= rDoc
.GetFormatTable();
1517 pFormatter
->PutEntry(aNewFormat
, nCheckPos
, nType
, nFormat
);
1518 rDoc
.SetNumberFormat(ScAddress(0, 0, 0), nFormat
);
1523 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testBlankInExponent
)
1525 createScDoc("ods/tdf156449-Blank-In-Exponent.ods");
1527 // save to ODS and reload
1528 saveAndReload("calc8");
1529 lcl_TestNumberFormat(*getScDoc(), "0.00E+?0");
1530 lcl_SetNumberFormat(*getScDoc(), "0.00E+??");
1531 // at least one '0' in exponent
1532 saveAndReload("calc8");
1533 lcl_TestNumberFormat(*getScDoc(), "0.00E+?0");
1535 // save to XLSX and reload
1536 saveAndReload("Calc Office Open XML");
1537 lcl_TestNumberFormat(*getScDoc(), "0.00E+?0");
1540 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testSecondsWithoutTruncateAndDecimals
)
1542 createScDoc("xlsx/seconds-without-truncate-and-decimals.xlsx");
1543 lcl_TestNumberFormat(*getScDoc(), "[SS].00");
1545 // save to ODS and reload
1546 saveAndReload("calc8");
1547 lcl_TestNumberFormat(*getScDoc(), "[SS].00");
1550 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testBlankWidthCharacter
)
1552 createScDoc("ods/tdf152724-Blank-width-char.ods");
1554 // save to ODS and reload
1555 saveAndReload("calc8");
1556 lcl_TestNumberFormat(*getScDoc(), "[>0]_-?0;[<0]-?0;_-?0;@");
1558 // save to XLSX and reload
1559 saveAndReload("Calc Office Open XML");
1560 lcl_TestNumberFormat(*getScDoc(), "_-?0;-?0;_-?0;@");
1563 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testEmbeddedTextInDecimal
)
1565 createScDoc("xlsx/embedded-text-in-decimal.xlsx");
1566 lcl_TestNumberFormat(*getScDoc(), "#,##0.000\" \"###\" \"###");
1568 // save to ODS and reload
1569 saveAndReload("calc8");
1570 lcl_TestNumberFormat(*getScDoc(), "#,##0.000\" \"###\" \"###");
1573 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testLowercaseExponent
)
1575 createScDoc("ods/tdf153993-Exponent-lower-case.ods");
1577 // save to ODS and reload
1578 saveAndReload("calc8");
1579 lcl_TestNumberFormat(*getScDoc(), "0.000\" \"000\" \"e+\" \"0");
1581 // save to XLSX and reload
1582 // lower case not preserve in XLSX
1583 saveAndReload("Calc Office Open XML");
1584 lcl_TestNumberFormat(*getScDoc(), "0.000 000 E+ 0");
1587 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTotalsRowFunction
)
1589 createScDoc("xlsx/totalsRowFunction.xlsx");
1590 saveAndReload("Calc Office Open XML");
1592 xmlDocUniquePtr pDocXml
= parseExport("xl/tables/table1.xml");
1593 CPPUNIT_ASSERT(pDocXml
);
1594 assertXPath(pDocXml
, "/x:table/x:tableColumns/x:tableColumn[5]"_ostr
,
1595 "totalsRowFunction"_ostr
, "sum");
1597 ScDocument
* pDoc
= getScDoc();
1598 pDoc
->InsertCol(ScRange(3, 0, 0, 3, pDoc
->MaxRow(), 0)); // Insert col 4
1599 saveAndReload("Calc Office Open XML");
1601 xmlDocUniquePtr pDocXml
= parseExport("xl/tables/table1.xml");
1602 CPPUNIT_ASSERT(pDocXml
);
1603 assertXPathNoAttribute(pDocXml
, "/x:table/x:tableColumns/x:tableColumn[5]"_ostr
,
1604 "totalsRowFunction"_ostr
);
1605 assertXPath(pDocXml
, "/x:table/x:tableColumns/x:tableColumn[6]"_ostr
,
1606 "totalsRowFunction"_ostr
, "sum");
1610 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testAutofilterHiddenButton
)
1612 createScDoc("xlsx/hiddenButton.xlsx");
1613 saveAndReload("Calc Office Open XML");
1614 xmlDocUniquePtr pDocXml
= parseExport("xl/tables/table1.xml");
1615 CPPUNIT_ASSERT(pDocXml
);
1616 for (int i
= 1; i
<= 5; i
++)
1619 = OString::Concat("/x:table/x:autoFilter/x:filterColumn[") + OString::number(i
) + "]";
1620 assertXPath(pDocXml
, sPath
, "hiddenButton"_ostr
, "1");
1624 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testShapeStyles
)
1629 uno::Reference
<lang::XMultiServiceFactory
> xMSF(mxComponent
, uno::UNO_QUERY_THROW
);
1630 uno::Reference
<style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier(mxComponent
,
1631 uno::UNO_QUERY_THROW
);
1632 uno::Reference
<container::XNameContainer
> xGraphicStyles(
1633 xStyleFamiliesSupplier
->getStyleFamilies()->getByName("GraphicStyles"),
1634 uno::UNO_QUERY_THROW
);
1637 uno::Reference
<style::XStyle
> xStyle(
1638 xMSF
->createInstance("com.sun.star.style.GraphicStyle"), uno::UNO_QUERY_THROW
);
1639 xGraphicStyles
->insertByName("MyStyle1", Any(xStyle
));
1640 uno::Reference
<beans::XPropertySet
> xPropertySet(xStyle
, uno::UNO_QUERY_THROW
);
1641 xPropertySet
->setPropertyValue("FillColor", Any(COL_RED
));
1642 xPropertySet
->setPropertyValue("FillTransparence", Any(sal_Int16(40)));
1644 xStyle
.set(xMSF
->createInstance("com.sun.star.style.GraphicStyle"), uno::UNO_QUERY_THROW
);
1645 xGraphicStyles
->insertByName("MyStyle2", Any(xStyle
));
1646 xStyle
->setParentStyle("MyStyle1");
1648 xStyle
.set(xMSF
->createInstance("com.sun.star.style.GraphicStyle"), uno::UNO_QUERY_THROW
);
1649 xGraphicStyles
->insertByName("MyStyle3", Any(xStyle
));
1650 xStyle
->setParentStyle("MyStyle2");
1653 uno::Reference
<drawing::XShape
> xShape(
1654 xMSF
->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY_THROW
);
1656 uno::Reference
<drawing::XDrawPagesSupplier
> xDPS(mxComponent
, uno::UNO_QUERY_THROW
);
1657 uno::Reference
<drawing::XShapes
> xShapes(xDPS
->getDrawPages()->getByIndex(0),
1658 uno::UNO_QUERY_THROW
);
1659 xShapes
->add(xShape
);
1660 uno::Reference
<beans::XPropertySet
>(xShape
, uno::UNO_QUERY_THROW
)
1661 ->setPropertyValue("Style", Any(xStyle
));
1664 saveAndReload("calc8");
1667 uno::Reference
<drawing::XDrawPagesSupplier
> xDPS(mxComponent
, uno::UNO_QUERY_THROW
);
1668 uno::Reference
<drawing::XShapes
> xShapes(xDPS
->getDrawPages()->getByIndex(0),
1669 uno::UNO_QUERY_THROW
);
1670 uno::Reference
<beans::XPropertySet
> xShape(xShapes
->getByIndex(0), uno::UNO_QUERY_THROW
);
1672 // check style hierarchy
1673 uno::Reference
<style::XStyle
> xStyle(xShape
->getPropertyValue("Style"),
1674 uno::UNO_QUERY_THROW
);
1675 CPPUNIT_ASSERT_EQUAL(OUString("MyStyle3"), xStyle
->getName());
1676 CPPUNIT_ASSERT_EQUAL(OUString("MyStyle2"), xStyle
->getParentStyle());
1678 // check that styles have effect on shapes
1680 xShape
->getPropertyValue("FillColor") >>= nColor
;
1681 CPPUNIT_ASSERT_EQUAL(COL_RED
, nColor
);
1682 CPPUNIT_ASSERT_EQUAL(sal_Int16(40),
1683 xShape
->getPropertyValue("FillTransparence").get
<sal_Int16
>());
1687 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testCommentStyles
)
1689 createScDoc("ods/comment.ods");
1692 ScDocument
* pDoc
= getScDoc();
1694 ScAddress
aPos(0, 0, 0);
1695 ScPostIt
* pNote
= pDoc
->GetNote(aPos
);
1696 CPPUNIT_ASSERT(pNote
);
1698 auto pCaption
= pNote
->GetCaption();
1699 CPPUNIT_ASSERT(pCaption
);
1701 // Check that we don't keep the shadow attribute as DF
1702 // (see ScNoteUtil::CreateNoteFromCaption)
1703 CPPUNIT_ASSERT_LESSEQUAL(SfxItemState::DEFAULT
,
1704 pCaption
->GetMergedItemSet().GetItemState(SDRATTR_SHADOW
, false));
1706 auto pStyleSheet
= &pDoc
->GetStyleSheetPool()->Make("MyStyle1", SfxStyleFamily::Frame
);
1707 auto& rSet
= pStyleSheet
->GetItemSet();
1708 rSet
.Put(SvxFontHeightItem(1129, 100, EE_CHAR_FONTHEIGHT
));
1710 pCaption
->SetStyleSheet(static_cast<SfxStyleSheet
*>(pStyleSheet
), false);
1712 // Hidden comments use different code path on import
1713 pNote
->ShowCaption(aPos
, false);
1716 saveAndReload("calc8");
1720 aDoc
.InitDrawLayer();
1721 aDoc
.TransferTab(*getScDoc(), 0, 0);
1723 ScAddress
aPos(0, 0, 0);
1724 ScPostIt
* pNote
= aDoc
.GetNote(aPos
);
1725 CPPUNIT_ASSERT(pNote
);
1727 auto pCaption
= pNote
->GetOrCreateCaption(aPos
);
1728 CPPUNIT_ASSERT(pCaption
);
1730 // Check that the style was imported, and survived copying
1731 CPPUNIT_ASSERT_EQUAL(OUString("MyStyle1"), pCaption
->GetStyleSheet()->GetName());
1734 saveAndReload("Calc Office Open XML");
1737 ScDocument
* pDoc
= getScDoc();
1739 ScAddress
aPos(0, 0, 0);
1740 ScPostIt
* pNote
= pDoc
->GetNote(aPos
);
1741 CPPUNIT_ASSERT(pNote
);
1743 auto pCaption
= pNote
->GetOrCreateCaption(aPos
);
1744 CPPUNIT_ASSERT(pCaption
);
1746 // Check that the style formatting is preserved
1747 CPPUNIT_ASSERT_EQUAL(sal_uInt32(1129),
1748 pCaption
->GetMergedItemSet().Get(EE_CHAR_FONTHEIGHT
).GetHeight());
1752 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf119565
)
1754 createScDoc("xlsx/tdf119565.xlsx");
1755 saveAndReload("Calc Office Open XML");
1757 uno::Reference
<drawing::XDrawPagesSupplier
> xDoc(mxComponent
, uno::UNO_QUERY_THROW
);
1758 uno::Reference
<drawing::XDrawPage
> xPage(xDoc
->getDrawPages()->getByIndex(0),
1759 uno::UNO_QUERY_THROW
);
1760 uno::Reference
<beans::XPropertySet
> xShapeProps(xPage
->getByIndex(0), uno::UNO_QUERY_THROW
);
1762 // Without the accompanying fix in place, this test would have failed with:
1765 // i.e. line width inherited from theme lost after export.
1766 CPPUNIT_ASSERT_EQUAL(sal_Int32(35),
1767 xShapeProps
->getPropertyValue("LineWidth").get
<sal_Int32
>());
1769 // Without the accompanying fix in place, this test would have failed with:
1772 // i.e. line joint inherited from theme lost after export.
1773 CPPUNIT_ASSERT_EQUAL(drawing::LineJoint_MITER
,
1774 xShapeProps
->getPropertyValue("LineJoint").get
<drawing::LineJoint
>());
1777 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf152980
)
1779 createScDoc("csv/tdf152980.csv");
1780 ScDocShell
* pDocSh
= getScDocShell();
1781 pDocSh
->DoHardRecalc();
1782 saveAndReload("Calc Office Open XML");
1783 pDocSh
= getScDocShell();
1784 pDocSh
->DoHardRecalc();
1786 ScDocument
* pDoc
= getScDoc();
1788 // - Expected: The part between a and b does not change
1789 // - Actual : Only the characters a and b remain
1790 CPPUNIT_ASSERT_EQUAL(OUString("a_x1_b"), pDoc
->GetString(0, 0, 0));
1791 CPPUNIT_ASSERT_EQUAL(OUString("a_x01_b"), pDoc
->GetString(0, 1, 0));
1792 CPPUNIT_ASSERT_EQUAL(OUString("a_x001_b"), pDoc
->GetString(0, 2, 0));
1794 // The character code does not change in both cases
1795 CPPUNIT_ASSERT_EQUAL(OUString("a_x0001_b"), pDoc
->GetString(0, 3, 0));
1797 // The escape characters are handled correctly in both cases
1798 CPPUNIT_ASSERT_EQUAL(OUString("a_xfoo\nb"), pDoc
->GetString(0, 4, 0));
1799 CPPUNIT_ASSERT_EQUAL(OUString("a\tb"), pDoc
->GetString(0, 5, 0));
1800 CPPUNIT_ASSERT_EQUAL(OUString("a\nb"), pDoc
->GetString(0, 6, 0));
1801 CPPUNIT_ASSERT_EQUAL(OUString("a\n\nb"), pDoc
->GetString(0, 7, 0));
1804 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf100034
)
1806 createScDoc("xlsx/tdf100034.xlsx");
1807 ScDocument
* pDoc
= getScDoc();
1809 // Clear print ranges (Format - Print Ranges - Clear)
1810 dispatchCommand(mxComponent
, ".uno:DeletePrintArea", {});
1812 // Save and load back
1813 saveAndReload("Calc Office Open XML");
1815 // Check if the same print ranges are present
1817 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(0), pDoc
->GetPrintRangeCount(0));
1820 CPPUNIT_TEST_FIXTURE(ScExportTest4
, testTdf157318
)
1822 // This document has 2 named ranges; Test1 is global; Test2 is linked to Sheet1)
1823 createScDoc("ods/tdf157318.ods");
1824 ScDocument
* pDoc
= getScDoc();
1826 // Save as XLSX and load back
1827 saveAndReload("Calc Office Open XML");
1830 // Check if there is one global named range
1831 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(1),
1832 static_cast<sal_uInt16
>(pDoc
->GetRangeName()->size()));
1834 // Check if there is one named range in the first sheet
1835 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16
>(1),
1836 static_cast<sal_uInt16
>(pDoc
->GetRangeName(0)->size()));
1839 CPPUNIT_PLUGIN_IMPLEMENT();
1841 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */