Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 :
10 : #include "qahelper.hxx"
11 : #include "csv_handler.hxx"
12 : #include "drwlayer.hxx"
13 : #include "compiler.hxx"
14 : #include "conditio.hxx"
15 : #include "stlsheet.hxx"
16 : #include "formulacell.hxx"
17 : #include <svx/svdpage.hxx>
18 : #include <svx/svdoole2.hxx>
19 : #include <editeng/brushitem.hxx>
20 : #include <editeng/justifyitem.hxx>
21 :
22 : #include <config_orcus.h>
23 :
24 : #if ENABLE_ORCUS
25 : #if defined WNT
26 : #define __ORCUS_STATIC_LIB
27 : #endif
28 : #include <orcus/csv_parser.hpp>
29 : #endif
30 :
31 : #include <fstream>
32 :
33 : #include <com/sun/star/frame/XModel.hpp>
34 : #include <com/sun/star/text/textfield/Type.hpp>
35 : #include <com/sun/star/chart2/XChartDocument.hpp>
36 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
37 :
38 : using namespace com::sun::star;
39 : using namespace ::com::sun::star::uno;
40 :
41 : // calc data structure pretty printer
42 0 : std::ostream& operator<<(std::ostream& rStrm, const ScAddress& rAddr)
43 : {
44 0 : rStrm << "Col: " << rAddr.Col() << " Row: " << rAddr.Row() << " Tab: " << rAddr.Tab() << "\n";
45 0 : return rStrm;
46 : }
47 :
48 0 : std::ostream& operator<<(std::ostream& rStrm, const ScRange& rRange)
49 : {
50 0 : rStrm << "ScRange: " << rRange.aStart << rRange.aEnd << "\n";
51 0 : return rStrm;
52 : }
53 :
54 0 : std::ostream& operator<<(std::ostream& rStrm, const ScRangeList& rList)
55 : {
56 0 : rStrm << "ScRangeList: \n";
57 0 : for(size_t i = 0; i < rList.size(); ++i)
58 0 : rStrm << *rList[i];
59 0 : return rStrm;
60 : }
61 :
62 0 : std::ostream& operator<<(std::ostream& rStrm, const Color& rColor)
63 : {
64 0 : rStrm << "Color: R:" << rColor.GetRed() << " G:" << rColor.GetGreen() << " B: << rColor.GetBlue()";
65 0 : return rStrm;
66 : }
67 :
68 : FileFormat aFileFormats[] = {
69 : { "ods" , "calc8", "", ODS_FORMAT_TYPE },
70 : { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE },
71 : { "xlsx", "Calc Office Open XML" , "Office Open XML Spreadsheet", XLSX_FORMAT_TYPE },
72 : { "xlsm", "Calc Office Open XML" , "Office Open XML Spreadsheet", XLSX_FORMAT_TYPE },
73 : { "csv" , "Text - txt - csv (StarCalc)", "generic_Text", CSV_FORMAT_TYPE },
74 : { "html" , "calc_HTML_WebQuery", "generic_HTML", HTML_FORMAT_TYPE },
75 : { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE },
76 : { "dif", "DIF", "calc_DIF", DIF_FORMAT_TYPE },
77 : { "xml", "MS Excel 2003 XML", "calc_MS_Excel_2003_XML", XLS_XML_FORMAT_TYPE }
78 : };
79 :
80 52 : bool testEqualsWithTolerance( long nVal1, long nVal2, long nTol )
81 : {
82 52 : return ( labs( nVal1 - nVal2 ) <= nTol );
83 : }
84 :
85 84 : void loadFile(const OUString& aFileName, std::string& aContent)
86 : {
87 84 : OString aOFileName = OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8);
88 :
89 : #ifdef ANDROID
90 : size_t size;
91 : if (strncmp(aOFileName.getStr(), "/assets/", sizeof("/assets/")-1) == 0) {
92 : const char *contents = (const char *) lo_apkentry(aOFileName.getStr(), &size);
93 : if (contents != 0) {
94 : aContent = std::string(contents, size);
95 : return;
96 : }
97 : }
98 : #endif
99 :
100 168 : std::ifstream aFile(aOFileName.getStr());
101 :
102 168 : OStringBuffer aErrorMsg("Could not open csv file: ");
103 84 : aErrorMsg.append(aOFileName);
104 84 : CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), aFile);
105 168 : std::ostringstream aOStream;
106 84 : aOStream << aFile.rdbuf();
107 84 : aFile.close();
108 168 : aContent = aOStream.str();
109 84 : }
110 :
111 : #if ENABLE_ORCUS
112 :
113 70 : void testFile(OUString& aFileName, ScDocument& rDoc, SCTAB nTab, StringType aStringFormat)
114 : {
115 70 : csv_handler aHandler(&rDoc, nTab, aStringFormat);
116 70 : orcus::csv::parser_config aConfig;
117 70 : aConfig.delimiters.push_back(',');
118 70 : aConfig.delimiters.push_back(';');
119 70 : aConfig.text_qualifier = '"';
120 70 : aConfig.trim_cell_value = false;
121 :
122 140 : std::string aContent;
123 70 : loadFile(aFileName, aContent);
124 140 : orcus::csv_parser<csv_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
125 : try
126 : {
127 70 : parser.parse();
128 : }
129 0 : catch (const orcus::csv::parse_error& e)
130 : {
131 0 : std::cout << "reading csv content file failed: " << e.what() << std::endl;
132 0 : OStringBuffer aErrorMsg("csv parser error: ");
133 0 : aErrorMsg.append(e.what());
134 0 : CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), false);
135 70 : }
136 70 : }
137 :
138 14 : void testCondFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab)
139 : {
140 14 : conditional_format_handler aHandler(pDoc, nTab);
141 14 : orcus::csv::parser_config aConfig;
142 14 : aConfig.delimiters.push_back(',');
143 14 : aConfig.delimiters.push_back(';');
144 14 : aConfig.text_qualifier = '"';
145 28 : std::string aContent;
146 14 : loadFile(aFileName, aContent);
147 28 : orcus::csv_parser<conditional_format_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
148 : try
149 : {
150 14 : parser.parse();
151 : }
152 0 : catch (const orcus::csv::parse_error& e)
153 : {
154 0 : std::cout << "reading csv content file failed: " << e.what() << std::endl;
155 0 : OStringBuffer aErrorMsg("csv parser error: ");
156 0 : aErrorMsg.append(e.what());
157 0 : CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), false);
158 14 : }
159 14 : }
160 :
161 : #else
162 :
163 : void testFile(OUString&, ScDocument&, SCTAB, StringType) {}
164 : void testCondFile(OUString&, ScDocument*, SCTAB) {}
165 :
166 : #endif
167 :
168 4 : void testFormats(ScBootstrapFixture* pTest, ScDocument* pDoc, sal_Int32 nFormat)
169 : {
170 : //test Sheet1 with csv file
171 4 : OUString aCSVFileName;
172 4 : pTest->createCSVPath(OUString("numberFormat."), aCSVFileName);
173 4 : testFile(aCSVFileName, *pDoc, 0, PureString);
174 : //need to test the color of B3
175 : //it's not a font color!
176 : //formatting for B5: # ??/100 gets lost during import
177 :
178 : //test Sheet2
179 4 : const ScPatternAttr* pPattern = NULL;
180 4 : pPattern = pDoc->GetPattern(0,0,1);
181 8 : vcl::Font aFont;
182 4 : pPattern->GetFont(aFont,SC_AUTOCOL_RAW);
183 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font size should be 10", 200l, aFont.GetSize().getHeight());
184 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font color should be black", COL_AUTO, aFont.GetColor().GetColor());
185 4 : pPattern = pDoc->GetPattern(0,1,1);
186 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
187 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font size should be 12", 240l, aFont.GetSize().getHeight());
188 4 : pPattern = pDoc->GetPattern(0,2,1);
189 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
190 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be italic", ITALIC_NORMAL, aFont.GetItalic());
191 4 : pPattern = pDoc->GetPattern(0,4,1);
192 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
193 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight());
194 4 : pPattern = pDoc->GetPattern(1,0,1);
195 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
196 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be blue", COL_BLUE, aFont.GetColor().GetColor());
197 4 : pPattern = pDoc->GetPattern(1,1,1);
198 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
199 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be striked out with a single line", STRIKEOUT_SINGLE, aFont.GetStrikeout());
200 : //some tests on sheet2 only for ods
201 4 : if (nFormat == ODS)
202 : {
203 4 : pPattern = pDoc->GetPattern(1,2,1);
204 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
205 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be striked out with a double line", STRIKEOUT_DOUBLE, aFont.GetStrikeout());
206 4 : pPattern = pDoc->GetPattern(1,3,1);
207 4 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
208 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be underlined with a dotted line", UNDERLINE_DOTTED, aFont.GetUnderline());
209 : //check row height import
210 : //disable for now until we figure out cause of win tinderboxes test failures
211 : //CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(256), pDoc->GetRowHeight(0,1) ); //0.178in
212 : //CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(304), pDoc->GetRowHeight(1,1) ); //0.211in
213 : //CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(477), pDoc->GetRowHeight(5,1) ); //0.3311in
214 : //check column width import
215 4 : CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(555), pDoc->GetColWidth(4,1) ); //0.3854in
216 4 : CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1280), pDoc->GetColWidth(5,1) ); //0.889in
217 4 : CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(4153), pDoc->GetColWidth(6,1) ); //2.8839in
218 : //test case for i53253 where a cell has text with different styles and space between the text.
219 4 : OUString aTestStr = pDoc->GetString(3,0,1);
220 8 : OUString aKnownGoodStr("text14 space");
221 4 : CPPUNIT_ASSERT_EQUAL( aKnownGoodStr, aTestStr );
222 : //test case for cell text with line breaks.
223 4 : aTestStr = pDoc->GetString(3,5,1);
224 4 : aKnownGoodStr = "Hello,\nCalc!";
225 8 : CPPUNIT_ASSERT_EQUAL( aKnownGoodStr, aTestStr );
226 : }
227 4 : pPattern = pDoc->GetPattern(1,4,1);
228 4 : Color aColor = static_cast<const SvxBrushItem&>(pPattern->GetItem(ATTR_BACKGROUND)).GetColor();
229 4 : CPPUNIT_ASSERT_MESSAGE("background color should be green", aColor == COL_LIGHTGREEN);
230 4 : pPattern = pDoc->GetPattern(2,0,1);
231 4 : SvxCellHorJustify eHorJustify = static_cast<SvxCellHorJustify>(static_cast<const SvxHorJustifyItem&>(pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue());
232 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("cell content should be aligned centre horizontally", SVX_HOR_JUSTIFY_CENTER, eHorJustify);
233 : //test alignment
234 4 : pPattern = pDoc->GetPattern(2,1,1);
235 4 : eHorJustify = static_cast<SvxCellHorJustify>(static_cast<const SvxHorJustifyItem&>(pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue());
236 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("cell content should be aligned right horizontally", SVX_HOR_JUSTIFY_RIGHT, eHorJustify);
237 4 : pPattern = pDoc->GetPattern(2,2,1);
238 4 : eHorJustify = static_cast<SvxCellHorJustify>(static_cast<const SvxHorJustifyItem&>(pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue());
239 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE("cell content should be aligned block horizontally", SVX_HOR_JUSTIFY_BLOCK, eHorJustify);
240 :
241 : //test Sheet3 only for ods and xlsx
242 4 : if ( nFormat == ODS || nFormat == XLSX )
243 : {
244 4 : pTest->createCSVPath(OUString("conditionalFormatting."), aCSVFileName);
245 4 : testCondFile(aCSVFileName, pDoc, 2);
246 : // test parent cell style import ( fdo#55198 )
247 4 : if ( nFormat == XLSX )
248 : {
249 0 : pPattern = pDoc->GetPattern(1,1,3);
250 0 : ScStyleSheet* pStyleSheet = (ScStyleSheet*)pPattern->GetStyleSheet();
251 : // check parent style name
252 0 : OUString sExpected("Excel Built-in Date");
253 0 : OUString sResult = pStyleSheet->GetName();
254 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE("parent style for Sheet4.B2 is 'Excel Built-in Date'", sExpected, sResult);
255 : // check align of style
256 0 : SfxItemSet& rItemSet = pStyleSheet->GetItemSet();
257 0 : eHorJustify = static_cast<SvxCellHorJustify>(static_cast< const SvxHorJustifyItem& >(rItemSet.Get( ATTR_HOR_JUSTIFY ) ).GetValue() );
258 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE("'Excel Built-in Date' style should be aligned centre horizontally", SVX_HOR_JUSTIFY_CENTER, eHorJustify);
259 : // check date format ( should be just month e.g. 29 )
260 0 : sResult =pDoc->GetString( 1,1,3 );
261 0 : sExpected = "29";
262 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE("'Excel Built-in Date' style should just display month", sExpected, sResult );
263 :
264 : // check actual align applied to cell, should be the same as
265 : // the style
266 0 : eHorJustify = static_cast<SvxCellHorJustify>(static_cast< const SvxHorJustifyItem& >(pPattern->GetItem( ATTR_HOR_JUSTIFY ) ).GetValue() );
267 0 : CPPUNIT_ASSERT_EQUAL_MESSAGE("cell with 'Excel Built-in Date' style should be aligned centre horizontally", SVX_HOR_JUSTIFY_CENTER, eHorJustify);
268 : }
269 : }
270 :
271 4 : ScConditionalFormat* pCondFormat = pDoc->GetCondFormat(0,0,2);
272 4 : const ScRangeList& rRange = pCondFormat->GetRange();
273 4 : CPPUNIT_ASSERT(rRange == ScRange(0,0,2,3,0,2));
274 :
275 4 : pCondFormat = pDoc->GetCondFormat(0,1,2);
276 4 : const ScRangeList& rRange2 = pCondFormat->GetRange();
277 4 : CPPUNIT_ASSERT(rRange2 == ScRange(0,1,2,0,1,2));
278 :
279 4 : pCondFormat = pDoc->GetCondFormat(1,1,2);
280 4 : const ScRangeList& rRange3 = pCondFormat->GetRange();
281 8 : CPPUNIT_ASSERT(rRange3 == ScRange(1,1,2,3,1,2));
282 4 : }
283 :
284 4 : const SdrOle2Obj* getSingleChartObject(ScDocument& rDoc, sal_uInt16 nPage)
285 : {
286 : // Retrieve the chart object instance from the 2nd page (for the 2nd sheet).
287 4 : ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
288 4 : if (!pDrawLayer)
289 : {
290 0 : cout << "Failed to retrieve the drawing layer object." << endl;
291 0 : return NULL;
292 : }
293 :
294 4 : const SdrPage* pPage = pDrawLayer->GetPage(nPage);
295 4 : if (!pPage)
296 : {
297 0 : cout << "Failed to retrieve the page object." << endl;
298 0 : return NULL;
299 : }
300 :
301 4 : if (pPage->GetObjCount() != 1)
302 : {
303 0 : cout << "This page should contain one drawing object." << endl;
304 0 : return NULL;
305 : }
306 :
307 4 : const SdrObject* pObj = pPage->GetObj(0);
308 4 : if (!pObj)
309 : {
310 0 : cout << "Failed to retrieve the drawing object." << endl;
311 0 : return NULL;
312 : }
313 :
314 4 : if (pObj->GetObjIdentifier() != OBJ_OLE2)
315 : {
316 0 : cout << "This is not an OLE2 object." << endl;
317 0 : return NULL;
318 : }
319 :
320 4 : const SdrOle2Obj& rOleObj = static_cast<const SdrOle2Obj&>(*pObj);
321 4 : if (!rOleObj.IsChart())
322 : {
323 0 : cout << "This should be a chart object." << endl;
324 0 : return NULL;
325 : }
326 :
327 4 : return &rOleObj;
328 : }
329 :
330 4 : std::vector<OUString> getChartRangeRepresentations(const SdrOle2Obj& rChartObj)
331 : {
332 4 : std::vector<OUString> aRangeReps;
333 :
334 : // Make sure the chart object has correct range references.
335 8 : Reference<frame::XModel> xModel = rChartObj.getXModel();
336 4 : if (!xModel.is())
337 : {
338 0 : cout << "Failed to get the embedded object interface." << endl;
339 0 : return aRangeReps;
340 : }
341 :
342 8 : Reference<chart2::XChartDocument> xChartDoc(xModel, UNO_QUERY);
343 4 : if (!xChartDoc.is())
344 : {
345 0 : cout << "Failed to get the chart document interface." << endl;
346 0 : return aRangeReps;
347 : }
348 :
349 8 : Reference<chart2::data::XDataSource> xDataSource(xChartDoc, UNO_QUERY);
350 4 : if (!xDataSource.is())
351 : {
352 0 : cout << "Failed to get the data source interface." << endl;
353 0 : return aRangeReps;
354 : }
355 :
356 8 : Sequence<Reference<chart2::data::XLabeledDataSequence> > xDataSeqs = xDataSource->getDataSequences();
357 4 : if (!xDataSeqs.getLength())
358 : {
359 0 : cout << "There should be at least one data sequences." << endl;
360 0 : return aRangeReps;
361 : }
362 :
363 8 : Reference<chart2::data::XDataReceiver> xDataRec(xChartDoc, UNO_QUERY);
364 4 : if (!xDataRec.is())
365 : {
366 0 : cout << "Failed to get the data receiver interface." << endl;
367 0 : return aRangeReps;
368 : }
369 :
370 8 : Sequence<OUString> aRangeRepSeqs = xDataRec->getUsedRangeRepresentations();
371 16 : for (sal_Int32 i = 0, n = aRangeRepSeqs.getLength(); i < n; ++i)
372 12 : aRangeReps.push_back(aRangeRepSeqs[i]);
373 :
374 4 : return aRangeReps;
375 : }
376 :
377 4 : ScRangeList getChartRanges(ScDocument& rDoc, const SdrOle2Obj& rChartObj)
378 : {
379 4 : std::vector<OUString> aRangeReps = getChartRangeRepresentations(rChartObj);
380 4 : ScRangeList aRanges;
381 16 : for (size_t i = 0, n = aRangeReps.size(); i < n; ++i)
382 : {
383 12 : ScRange aRange;
384 12 : sal_uInt16 nRes = aRange.Parse(aRangeReps[i], &rDoc, rDoc.GetAddressConvention());
385 12 : if (nRes & SCA_VALID)
386 : // This is a range address.
387 8 : aRanges.Append(aRange);
388 : else
389 : {
390 : // Parse it as a single cell address.
391 4 : ScAddress aAddr;
392 4 : nRes = aAddr.Parse(aRangeReps[i], &rDoc, rDoc.GetAddressConvention());
393 4 : CPPUNIT_ASSERT_MESSAGE("Failed to parse a range representation.", (nRes & SCA_VALID));
394 4 : aRanges.Append(aAddr);
395 : }
396 : }
397 :
398 4 : return aRanges;
399 : }
400 :
401 : namespace {
402 :
403 758 : ScTokenArray* getTokens(ScDocument& rDoc, const ScAddress& rPos)
404 : {
405 758 : ScFormulaCell* pCell = rDoc.GetFormulaCell(rPos);
406 758 : if (!pCell)
407 : {
408 0 : OUString aStr = rPos.Format(SCA_VALID);
409 0 : cerr << aStr << " is not a formula cell." << endl;
410 0 : return NULL;
411 : }
412 :
413 758 : return pCell->GetCode();
414 : }
415 :
416 : }
417 :
418 758 : bool checkFormula(ScDocument& rDoc, const ScAddress& rPos, const char* pExpected)
419 : {
420 758 : ScTokenArray* pCode = getTokens(rDoc, rPos);
421 758 : if (!pCode)
422 : {
423 0 : cerr << "Empty token array." << endl;
424 0 : return false;
425 : }
426 :
427 758 : OUString aFormula = toString(rDoc, rPos, *pCode, rDoc.GetGrammar());
428 758 : if (aFormula != OUString::createFromAscii(pExpected))
429 : {
430 0 : cerr << "Formula '" << pExpected << "' expected, but '" << aFormula << "' found" << endl;
431 0 : return false;
432 : }
433 :
434 758 : return true;
435 : }
436 :
437 12 : bool checkFormulaPosition(ScDocument& rDoc, const ScAddress& rPos)
438 : {
439 12 : OUString aStr(rPos.Format(SCA_VALID));
440 12 : const ScFormulaCell* pFC = rDoc.GetFormulaCell(rPos);
441 12 : if (!pFC)
442 : {
443 0 : cerr << "Formula cell expected at " << aStr << " but not found." << endl;
444 0 : return false;
445 : }
446 :
447 12 : if (pFC->aPos != rPos)
448 : {
449 0 : OUString aStr2(pFC->aPos.Format(SCA_VALID));
450 0 : cerr << "Formula cell at " << aStr << " has incorrect position of " << aStr2 << endl;
451 0 : return false;
452 : }
453 :
454 12 : return true;
455 : }
456 :
457 4 : bool checkFormulaPositions(
458 : ScDocument& rDoc, SCTAB nTab, SCCOL nCol, const SCROW* pRows, size_t nRowCount)
459 : {
460 4 : ScAddress aPos(nCol, 0, nTab);
461 16 : for (size_t i = 0; i < nRowCount; ++i)
462 : {
463 12 : SCROW nRow = pRows[i];
464 12 : aPos.SetRow(nRow);
465 :
466 12 : if (!checkFormulaPosition(rDoc, aPos))
467 : {
468 0 : OUString aStr(aPos.Format(SCA_VALID));
469 0 : cerr << "Formula cell position failed at " << aStr << "." << endl;
470 0 : return false;
471 : }
472 : }
473 4 : return true;
474 : }
475 :
476 10 : ScTokenArray* compileFormula(
477 : ScDocument* pDoc, const OUString& rFormula, const ScAddress* pPos,
478 : formula::FormulaGrammar::Grammar eGram )
479 : {
480 10 : ScAddress aPos(0,0,0);
481 10 : if (pPos)
482 0 : aPos = *pPos;
483 10 : ScCompiler aComp(pDoc, aPos);
484 10 : aComp.SetGrammar(eGram);
485 10 : return aComp.CompileString(rFormula);
486 : }
487 :
488 0 : void clearFormulaCellChangedFlag( ScDocument& rDoc, const ScRange& rRange )
489 : {
490 0 : const ScAddress& s = rRange.aStart;
491 0 : const ScAddress& e = rRange.aEnd;
492 0 : for (SCTAB nTab = s.Tab(); nTab <= e.Tab(); ++nTab)
493 : {
494 0 : for (SCCOL nCol = s.Col(); nCol <= e.Col(); ++nCol)
495 : {
496 0 : for (SCROW nRow = s.Row(); nRow <= e.Row(); ++nRow)
497 : {
498 0 : ScAddress aPos(nCol, nRow, nTab);
499 0 : ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
500 0 : if (pFC)
501 0 : pFC->SetChanged(false);
502 : }
503 : }
504 : }
505 0 : }
506 :
507 456 : bool isFormulaWithoutError(ScDocument& rDoc, const ScAddress& rPos)
508 : {
509 456 : ScFormulaCell* pFC = rDoc.GetFormulaCell(rPos);
510 456 : if (!pFC)
511 0 : return false;
512 :
513 456 : return pFC->GetErrCode() == 0;
514 : }
515 :
516 766 : OUString toString(
517 : ScDocument& rDoc, const ScAddress& rPos, ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram)
518 : {
519 766 : ScCompiler aComp(&rDoc, rPos, rArray);
520 766 : aComp.SetGrammar(eGram);
521 1532 : OUStringBuffer aBuf;
522 766 : aComp.CreateStringFromTokenArray(aBuf);
523 1532 : return aBuf.makeStringAndClear();
524 : }
525 :
526 374 : ScDocShellRef ScBootstrapFixture::load( bool bReadWrite,
527 : const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
528 : const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID,
529 : sal_uIntPtr nFilterVersion, const OUString* pPassword )
530 : {
531 : SfxFilter* pFilter = new SfxFilter(
532 : rFilter,
533 : OUString(), nFilterFlags, nClipboardID, rTypeName, 0, OUString(),
534 374 : rUserData, OUString("private:factory/scalc*"));
535 374 : pFilter->SetVersion(nFilterVersion);
536 :
537 374 : ScDocShellRef xDocShRef = new ScDocShell;
538 374 : xDocShRef->GetDocument().EnableUserInteraction(false);
539 374 : SfxMedium* pSrcMed = new SfxMedium(rURL, bReadWrite ? STREAM_STD_READWRITE : STREAM_STD_READ );
540 374 : pSrcMed->SetFilter(pFilter);
541 374 : pSrcMed->UseInteractionHandler(false);
542 374 : if (pPassword)
543 : {
544 2 : SfxItemSet* pSet = pSrcMed->GetItemSet();
545 2 : pSet->Put(SfxStringItem(SID_PASSWORD, *pPassword));
546 : }
547 : SAL_INFO( "sc.qa", "about to load " << rURL );
548 374 : if (!xDocShRef->DoLoad(pSrcMed))
549 : {
550 8 : xDocShRef->DoClose();
551 : // load failed.
552 8 : xDocShRef.Clear();
553 : }
554 :
555 374 : return xDocShRef;
556 : }
557 :
558 136 : ScDocShellRef ScBootstrapFixture::load(
559 : const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
560 : const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID,
561 : sal_uIntPtr nFilterVersion, const OUString* pPassword )
562 : {
563 136 : return load( false, rURL, rFilter, rUserData, rTypeName, nFilterFlags, nClipboardID, nFilterVersion, pPassword );
564 : }
565 :
566 238 : ScDocShellRef ScBootstrapFixture::loadDoc(
567 : const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite )
568 : {
569 238 : OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
570 476 : OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
571 476 : OUString aFileName;
572 238 : createFileURL( rFileName, aFileExtension, aFileName );
573 476 : OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
574 238 : unsigned int nFormatType = aFileFormats[nFormat].nFormatType;
575 238 : unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
576 :
577 476 : return load(bReadWrite, aFileName, aFilterName, OUString(), aFilterType, nFormatType, nClipboardId, nFormatType);
578 : }
579 :
580 84 : const FileFormat* ScBootstrapFixture::getFileFormats()
581 : {
582 84 : return aFileFormats;
583 : }
584 :
585 680 : ScBootstrapFixture::ScBootstrapFixture( const OUString& rsBaseString ) : m_aBaseString( rsBaseString ) {}
586 680 : ScBootstrapFixture::~ScBootstrapFixture() {}
587 :
588 248 : void ScBootstrapFixture::createFileURL(
589 : const OUString& aFileBase, const OUString& aFileExtension, OUString& rFilePath)
590 : {
591 248 : OUString aSep("/");
592 496 : OUStringBuffer aBuffer( getSrcRootURL() );
593 248 : aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
594 248 : aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
595 496 : rFilePath = aBuffer.makeStringAndClear();
596 248 : }
597 :
598 84 : void ScBootstrapFixture::createCSVPath(const OUString& aFileBase, OUString& rCSVPath)
599 : {
600 84 : OUStringBuffer aBuffer( getSrcRootPath());
601 84 : aBuffer.append(m_aBaseString).append("/contentCSV/");
602 84 : aBuffer.append(aFileBase).append("csv");
603 84 : rCSVPath = aBuffer.makeStringAndClear();
604 84 : }
605 :
606 80 : ScDocShellRef ScBootstrapFixture::saveAndReload(
607 : ScDocShell* pShell, const OUString &rFilter,
608 : const OUString &rUserData, const OUString& rTypeName, sal_uLong nFormatType)
609 : {
610 :
611 80 : utl::TempFile aTempFile;
612 160 : SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
613 80 : sal_uInt32 nExportFormat = 0;
614 80 : if (nFormatType == ODS_FORMAT_TYPE)
615 30 : nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
616 : SfxFilter* pExportFilter = new SfxFilter(
617 : rFilter,
618 : OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
619 80 : rUserData, OUString("private:factory/scalc*") );
620 80 : pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
621 80 : aStoreMedium.SetFilter(pExportFilter);
622 80 : pShell->DoSaveAs( aStoreMedium );
623 80 : pShell->DoClose();
624 :
625 : //std::cout << "File: " << aTempFile.GetURL() << std::endl;
626 :
627 80 : sal_uInt32 nFormat = 0;
628 80 : if (nFormatType == ODS_FORMAT_TYPE)
629 30 : nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
630 :
631 80 : ScDocShellRef xDocSh = load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat );
632 80 : if(nFormatType == XLSX_FORMAT_TYPE)
633 28 : validate(aTempFile.GetFileName(), test::OOXML);
634 52 : else if (nFormatType == ODS_FORMAT_TYPE)
635 30 : validate(aTempFile.GetFileName(), test::ODF);
636 80 : aTempFile.EnableKillingFile();
637 160 : return xDocSh;
638 : }
639 :
640 80 : ScDocShellRef ScBootstrapFixture::saveAndReload( ScDocShell* pShell, sal_Int32 nFormat )
641 : {
642 80 : OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
643 160 : OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
644 80 : ScDocShellRef xDocSh = saveAndReload(pShell, aFilterName, OUString(), aFilterType, aFileFormats[nFormat].nFormatType);
645 :
646 80 : CPPUNIT_ASSERT(xDocSh.Is());
647 160 : return xDocSh;
648 : }
649 :
650 2 : boost::shared_ptr<utl::TempFile> ScBootstrapFixture::exportTo( ScDocShell* pShell, sal_Int32 nFormat )
651 : {
652 2 : OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
653 4 : OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
654 :
655 2 : boost::shared_ptr<utl::TempFile> pTempFile(new utl::TempFile());
656 2 : pTempFile->EnableKillingFile();
657 4 : SfxMedium aStoreMedium( pTempFile->GetURL(), STREAM_STD_WRITE );
658 2 : sal_uInt32 nExportFormat = 0;
659 2 : sal_Int32 nFormatType = aFileFormats[nFormat].nFormatType;
660 2 : if (nFormatType == ODS_FORMAT_TYPE)
661 2 : nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
662 : SfxFilter* pExportFilter = new SfxFilter(
663 : aFilterName,
664 : OUString(), nFormatType, nExportFormat, aFilterType, 0, OUString(),
665 2 : OUString(), OUString("private:factory/scalc*") );
666 2 : pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
667 2 : aStoreMedium.SetFilter(pExportFilter);
668 2 : pShell->DoSaveAs( aStoreMedium );
669 2 : pShell->DoClose();
670 :
671 2 : if(nFormatType == XLSX_FORMAT_TYPE)
672 0 : validate(pTempFile->GetFileName(), test::OOXML);
673 2 : else if (nFormatType == ODS_FORMAT_TYPE)
674 2 : validate(pTempFile->GetFileName(), test::ODF);
675 :
676 4 : return pTempFile;
677 : }
678 :
679 4 : void ScBootstrapFixture::miscRowHeightsTest( TestParam* aTestValues, unsigned int numElems )
680 : {
681 16 : for ( unsigned int index=0; index<numElems; ++index )
682 : {
683 12 : OUString sFileName = OUString::createFromAscii( aTestValues[ index ].sTestDoc );
684 : SAL_INFO( "sc.qa", "aTestValues[" << index << "] " << sFileName );
685 12 : int nImportType = aTestValues[ index ].nImportType;
686 12 : int nExportType = aTestValues[ index ].nExportType;
687 24 : ScDocShellRef xShell = loadDoc( sFileName, nImportType );
688 12 : CPPUNIT_ASSERT(xShell.Is());
689 :
690 12 : if ( nExportType != -1 )
691 8 : xShell = saveAndReload(&(*xShell), nExportType );
692 :
693 12 : CPPUNIT_ASSERT(xShell.Is());
694 :
695 12 : ScDocument& rDoc = xShell->GetDocument();
696 :
697 48 : for (int i=0; i<aTestValues[ index ].nRowData; ++i)
698 : {
699 36 : SCROW nRow = aTestValues[ index ].pData[ i].nStartRow;
700 36 : SCROW nEndRow = aTestValues[ index ].pData[ i ].nEndRow;
701 36 : SCTAB nTab = aTestValues[ index ].pData[ i ].nTab;
702 36 : int nExpectedHeight = aTestValues[ index ].pData[ i ].nExpectedHeight;
703 36 : if ( nExpectedHeight == -1 )
704 4 : nExpectedHeight = sc::TwipsToHMM( ScGlobal::GetStandardRowHeight() );
705 36 : bool bCheckOpt = ( ( aTestValues[ index ].pData[ i ].nCheck & CHECK_OPTIMAL ) == CHECK_OPTIMAL );
706 184 : for ( ; nRow <= nEndRow; ++nRow )
707 : {
708 : SAL_INFO( "sc.qa", " checking row " << nRow << " for height " << nExpectedHeight );
709 148 : int nHeight = sc::TwipsToHMM( rDoc.GetRowHeight(nRow, nTab, false) );
710 148 : if ( bCheckOpt )
711 : {
712 4 : bool bOpt = !(rDoc.GetRowFlags( nRow, nTab ) & CR_MANUALSIZE);
713 4 : CPPUNIT_ASSERT_EQUAL(aTestValues[ index ].pData[ i ].bOptimal, bOpt);
714 : }
715 148 : CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight);
716 : }
717 : }
718 12 : xShell->DoClose();
719 12 : }
720 46 : }
721 :
722 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|