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 : { "csv" , "Text - txt - csv (StarCalc)", "generic_Text", CSV_FORMAT_TYPE },
73 : { "html" , "calc_HTML_WebQuery", "generic_HTML", HTML_FORMAT_TYPE },
74 : { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE },
75 : { "dif", "DIF", "calc_DIF", DIF_FORMAT_TYPE },
76 : { "xml", "MS Excel 2003 XML", "calc_MS_Excel_2003_XML", XLS_XML_FORMAT_TYPE }
77 : };
78 :
79 26 : bool testEqualsWithTolerance( long nVal1, long nVal2, long nTol )
80 : {
81 26 : return ( labs( nVal1 - nVal2 ) <= nTol );
82 : }
83 :
84 40 : void loadFile(const OUString& aFileName, std::string& aContent)
85 : {
86 40 : OString aOFileName = OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8);
87 :
88 : #ifdef ANDROID
89 : size_t size;
90 : if (strncmp(aOFileName.getStr(), "/assets/", sizeof("/assets/")-1) == 0) {
91 : const char *contents = (const char *) lo_apkentry(aOFileName.getStr(), &size);
92 : if (contents != 0) {
93 : aContent = std::string(contents, size);
94 : return;
95 : }
96 : }
97 : #endif
98 :
99 80 : std::ifstream aFile(aOFileName.getStr());
100 :
101 80 : OStringBuffer aErrorMsg("Could not open csv file: ");
102 40 : aErrorMsg.append(aOFileName);
103 40 : CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), aFile);
104 80 : std::ostringstream aOStream;
105 40 : aOStream << aFile.rdbuf();
106 40 : aFile.close();
107 80 : aContent = aOStream.str();
108 40 : }
109 :
110 : #if ENABLE_ORCUS
111 :
112 34 : void testFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab, StringType aStringFormat)
113 : {
114 34 : csv_handler aHandler(pDoc, nTab, aStringFormat);
115 34 : orcus::csv::parser_config aConfig;
116 34 : aConfig.delimiters.push_back(',');
117 34 : aConfig.delimiters.push_back(';');
118 34 : aConfig.text_qualifier = '"';
119 34 : aConfig.trim_cell_value = false;
120 :
121 :
122 68 : std::string aContent;
123 34 : loadFile(aFileName, aContent);
124 68 : orcus::csv_parser<csv_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
125 : try
126 : {
127 34 : 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 34 : }
136 34 : }
137 :
138 6 : void testCondFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab)
139 : {
140 6 : conditional_format_handler aHandler(pDoc, nTab);
141 6 : orcus::csv::parser_config aConfig;
142 6 : aConfig.delimiters.push_back(',');
143 6 : aConfig.delimiters.push_back(';');
144 6 : aConfig.text_qualifier = '"';
145 12 : std::string aContent;
146 6 : loadFile(aFileName, aContent);
147 12 : orcus::csv_parser<conditional_format_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
148 : try
149 : {
150 6 : 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 6 : }
159 6 : }
160 :
161 : #else
162 :
163 : void testFile(OUString&, ScDocument*, SCTAB, StringType) {}
164 : void testCondFile(OUString&, ScDocument*, SCTAB) {}
165 :
166 : #endif
167 :
168 2 : void testFormats(ScBootstrapFixture* pTest, ScDocument* pDoc, sal_Int32 nFormat)
169 : {
170 : //test Sheet1 with csv file
171 2 : OUString aCSVFileName;
172 2 : pTest->createCSVPath(OUString("numberFormat."), aCSVFileName);
173 2 : 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 2 : const ScPatternAttr* pPattern = NULL;
180 2 : pPattern = pDoc->GetPattern(0,0,1);
181 4 : Font aFont;
182 2 : pPattern->GetFont(aFont,SC_AUTOCOL_RAW);
183 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font size should be 10", 200l, aFont.GetSize().getHeight());
184 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font color should be black", COL_AUTO, aFont.GetColor().GetColor());
185 2 : pPattern = pDoc->GetPattern(0,1,1);
186 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
187 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font size should be 12", 240l, aFont.GetSize().getHeight());
188 2 : pPattern = pDoc->GetPattern(0,2,1);
189 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
190 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be italic", ITALIC_NORMAL, aFont.GetItalic());
191 2 : pPattern = pDoc->GetPattern(0,4,1);
192 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
193 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be bold", WEIGHT_BOLD, aFont.GetWeight());
194 2 : pPattern = pDoc->GetPattern(1,0,1);
195 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
196 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be blue", COL_BLUE, aFont.GetColor().GetColor());
197 2 : pPattern = pDoc->GetPattern(1,1,1);
198 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
199 2 : 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 2 : if (nFormat == ODS)
202 : {
203 2 : pPattern = pDoc->GetPattern(1,2,1);
204 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
205 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("font should be striked out with a double line", STRIKEOUT_DOUBLE, aFont.GetStrikeout());
206 2 : pPattern = pDoc->GetPattern(1,3,1);
207 2 : pPattern->GetFont(aFont, SC_AUTOCOL_RAW);
208 2 : 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 2 : CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(555), pDoc->GetColWidth(4,1) ); //0.3854in
216 2 : CPPUNIT_ASSERT_EQUAL( static_cast<sal_uInt16>(1280), pDoc->GetColWidth(5,1) ); //0.889in
217 2 : 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 2 : OUString aTestStr = pDoc->GetString(3,0,1);
220 4 : OUString aKnownGoodStr("text14 space");
221 2 : CPPUNIT_ASSERT_EQUAL( aKnownGoodStr, aTestStr );
222 : //test case for cell text with line breaks.
223 2 : aTestStr = pDoc->GetString(3,5,1);
224 2 : aKnownGoodStr = "Hello,\nCalc!";
225 4 : CPPUNIT_ASSERT_EQUAL( aKnownGoodStr, aTestStr );
226 : }
227 2 : pPattern = pDoc->GetPattern(1,4,1);
228 2 : Color aColor = static_cast<const SvxBrushItem&>(pPattern->GetItem(ATTR_BACKGROUND)).GetColor();
229 2 : CPPUNIT_ASSERT_MESSAGE("background color should be green", aColor == COL_LIGHTGREEN);
230 2 : pPattern = pDoc->GetPattern(2,0,1);
231 2 : SvxCellHorJustify eHorJustify = static_cast<SvxCellHorJustify>(static_cast<const SvxHorJustifyItem&>(pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue());
232 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("cell content should be aligned centre horizontally", SVX_HOR_JUSTIFY_CENTER, eHorJustify);
233 : //test alignment
234 2 : pPattern = pDoc->GetPattern(2,1,1);
235 2 : eHorJustify = static_cast<SvxCellHorJustify>(static_cast<const SvxHorJustifyItem&>(pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue());
236 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE("cell content should be aligned right horizontally", SVX_HOR_JUSTIFY_RIGHT, eHorJustify);
237 2 : pPattern = pDoc->GetPattern(2,2,1);
238 2 : eHorJustify = static_cast<SvxCellHorJustify>(static_cast<const SvxHorJustifyItem&>(pPattern->GetItem(ATTR_HOR_JUSTIFY)).GetValue());
239 2 : 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 2 : if ( nFormat == ODS || nFormat == XLSX )
243 : {
244 2 : pTest->createCSVPath(OUString("conditionalFormatting."), aCSVFileName);
245 2 : testCondFile(aCSVFileName, pDoc, 2);
246 : // test parent cell style import ( fdo#55198 )
247 2 : 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 2 : ScConditionalFormat* pCondFormat = pDoc->GetCondFormat(0,0,2);
272 2 : const ScRangeList& rRange = pCondFormat->GetRange();
273 2 : CPPUNIT_ASSERT(rRange == ScRange(0,0,2,3,0,2));
274 :
275 2 : pCondFormat = pDoc->GetCondFormat(0,1,2);
276 2 : const ScRangeList& rRange2 = pCondFormat->GetRange();
277 2 : CPPUNIT_ASSERT(rRange2 == ScRange(0,1,2,0,1,2));
278 :
279 2 : pCondFormat = pDoc->GetCondFormat(1,1,2);
280 2 : const ScRangeList& rRange3 = pCondFormat->GetRange();
281 4 : CPPUNIT_ASSERT(rRange3 == ScRange(1,1,2,3,1,2));
282 2 : }
283 :
284 2 : const SdrOle2Obj* getSingleChartObject(ScDocument& rDoc, sal_uInt16 nPage)
285 : {
286 : // Retrieve the chart object instance from the 2nd page (for the 2nd sheet).
287 2 : ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
288 2 : if (!pDrawLayer)
289 : {
290 0 : cout << "Failed to retrieve the drawing layer object." << endl;
291 0 : return NULL;
292 : }
293 :
294 2 : const SdrPage* pPage = pDrawLayer->GetPage(nPage);
295 2 : if (!pPage)
296 : {
297 0 : cout << "Failed to retrieve the page object." << endl;
298 0 : return NULL;
299 : }
300 :
301 2 : if (pPage->GetObjCount() != 1)
302 : {
303 0 : cout << "This page should contain one drawing object." << endl;
304 0 : return NULL;
305 : }
306 :
307 2 : const SdrObject* pObj = pPage->GetObj(0);
308 2 : if (!pObj)
309 : {
310 0 : cout << "Failed to retrieve the drawing object." << endl;
311 0 : return NULL;
312 : }
313 :
314 2 : if (pObj->GetObjIdentifier() != OBJ_OLE2)
315 : {
316 0 : cout << "This is not an OLE2 object." << endl;
317 0 : return NULL;
318 : }
319 :
320 2 : const SdrOle2Obj& rOleObj = static_cast<const SdrOle2Obj&>(*pObj);
321 2 : if (!rOleObj.IsChart())
322 : {
323 0 : cout << "This should be a chart object." << endl;
324 0 : return NULL;
325 : }
326 :
327 2 : return &rOleObj;
328 : }
329 :
330 2 : std::vector<OUString> getChartRangeRepresentations(const SdrOle2Obj& rChartObj)
331 : {
332 2 : std::vector<OUString> aRangeReps;
333 :
334 : // Make sure the chart object has correct range references.
335 4 : Reference<frame::XModel> xModel = rChartObj.getXModel();
336 2 : if (!xModel.is())
337 : {
338 0 : cout << "Failed to get the embedded object interface." << endl;
339 0 : return aRangeReps;
340 : }
341 :
342 4 : Reference<chart2::XChartDocument> xChartDoc(xModel, UNO_QUERY);
343 2 : if (!xChartDoc.is())
344 : {
345 0 : cout << "Failed to get the chart document interface." << endl;
346 0 : return aRangeReps;
347 : }
348 :
349 4 : Reference<chart2::data::XDataSource> xDataSource(xChartDoc, UNO_QUERY);
350 2 : if (!xDataSource.is())
351 : {
352 0 : cout << "Failed to get the data source interface." << endl;
353 0 : return aRangeReps;
354 : }
355 :
356 4 : Sequence<Reference<chart2::data::XLabeledDataSequence> > xDataSeqs = xDataSource->getDataSequences();
357 2 : if (!xDataSeqs.getLength())
358 : {
359 0 : cout << "There should be at least one data sequences." << endl;
360 0 : return aRangeReps;
361 : }
362 :
363 4 : Reference<chart2::data::XDataReceiver> xDataRec(xChartDoc, UNO_QUERY);
364 2 : if (!xDataRec.is())
365 : {
366 0 : cout << "Failed to get the data receiver interface." << endl;
367 0 : return aRangeReps;
368 : }
369 :
370 4 : Sequence<OUString> aRangeRepSeqs = xDataRec->getUsedRangeRepresentations();
371 8 : for (sal_Int32 i = 0, n = aRangeRepSeqs.getLength(); i < n; ++i)
372 6 : aRangeReps.push_back(aRangeRepSeqs[i]);
373 :
374 2 : return aRangeReps;
375 : }
376 :
377 2 : ScRangeList getChartRanges(ScDocument& rDoc, const SdrOle2Obj& rChartObj)
378 : {
379 2 : std::vector<OUString> aRangeReps = getChartRangeRepresentations(rChartObj);
380 2 : ScRangeList aRanges;
381 8 : for (size_t i = 0, n = aRangeReps.size(); i < n; ++i)
382 : {
383 6 : ScRange aRange;
384 6 : sal_uInt16 nRes = aRange.Parse(aRangeReps[i], &rDoc, rDoc.GetAddressConvention());
385 6 : if (nRes & SCA_VALID)
386 : // This is a range address.
387 4 : aRanges.Append(aRange);
388 : else
389 : {
390 : // Parse it as a single cell address.
391 2 : ScAddress aAddr;
392 2 : nRes = aAddr.Parse(aRangeReps[i], &rDoc, rDoc.GetAddressConvention());
393 2 : CPPUNIT_ASSERT_MESSAGE("Failed to parse a range representation.", (nRes & SCA_VALID));
394 2 : aRanges.Append(aAddr);
395 : }
396 : }
397 :
398 2 : return aRanges;
399 : }
400 :
401 : namespace {
402 :
403 271 : ScTokenArray* getTokens(ScDocument& rDoc, const ScAddress& rPos)
404 : {
405 271 : ScFormulaCell* pCell = rDoc.GetFormulaCell(rPos);
406 271 : if (!pCell)
407 0 : return NULL;
408 :
409 271 : return pCell->GetCode();
410 : }
411 :
412 : }
413 :
414 271 : bool checkFormula(ScDocument& rDoc, const ScAddress& rPos, const char* pExpected)
415 : {
416 271 : ScTokenArray* pCode = getTokens(rDoc, rPos);
417 271 : if (!pCode)
418 : {
419 0 : cerr << "Empty token array." << endl;
420 0 : return false;
421 : }
422 :
423 271 : OUString aFormula = toString(rDoc, rPos, *pCode, rDoc.GetGrammar());
424 271 : if (aFormula != OUString::createFromAscii(pExpected))
425 : {
426 0 : cerr << "Formula '" << pExpected << "' expected, but '" << aFormula << "' found" << endl;
427 0 : return false;
428 : }
429 :
430 271 : return true;
431 : }
432 :
433 6 : bool checkFormulaPosition(ScDocument& rDoc, const ScAddress& rPos)
434 : {
435 6 : OUString aStr(rPos.Format(SCA_VALID));
436 6 : const ScFormulaCell* pFC = rDoc.GetFormulaCell(rPos);
437 6 : if (!pFC)
438 : {
439 0 : cerr << "Formula cell expected at " << aStr << " but not found." << endl;
440 0 : return false;
441 : }
442 :
443 6 : if (pFC->aPos != rPos)
444 : {
445 0 : OUString aStr2(pFC->aPos.Format(SCA_VALID));
446 0 : cerr << "Formula cell at " << aStr << " has incorrect position of " << aStr2 << endl;
447 0 : return false;
448 : }
449 :
450 6 : return true;
451 : }
452 :
453 2 : bool checkFormulaPositions(
454 : ScDocument& rDoc, SCTAB nTab, SCCOL nCol, const SCROW* pRows, size_t nRowCount)
455 : {
456 2 : ScAddress aPos(nCol, 0, nTab);
457 8 : for (size_t i = 0; i < nRowCount; ++i)
458 : {
459 6 : SCROW nRow = pRows[i];
460 6 : aPos.SetRow(nRow);
461 :
462 6 : if (!checkFormulaPosition(rDoc, aPos))
463 : {
464 0 : OUString aStr(aPos.Format(SCA_VALID));
465 0 : cerr << "Formula cell position failed at " << aStr << "." << endl;
466 0 : return false;
467 : }
468 : }
469 2 : return true;
470 : }
471 :
472 0 : void clearFormulaCellChangedFlag( ScDocument& rDoc, const ScRange& rRange )
473 : {
474 0 : const ScAddress& s = rRange.aStart;
475 0 : const ScAddress& e = rRange.aEnd;
476 0 : for (SCTAB nTab = s.Tab(); nTab <= e.Tab(); ++nTab)
477 : {
478 0 : for (SCCOL nCol = s.Col(); nCol <= e.Col(); ++nCol)
479 : {
480 0 : for (SCROW nRow = s.Row(); nRow <= e.Row(); ++nRow)
481 : {
482 0 : ScAddress aPos(nCol, nRow, nTab);
483 0 : ScFormulaCell* pFC = rDoc.GetFormulaCell(aPos);
484 0 : if (pFC)
485 0 : pFC->SetChanged(false);
486 : }
487 : }
488 : }
489 0 : }
490 :
491 74 : bool isFormulaWithoutError(ScDocument& rDoc, const ScAddress& rPos)
492 : {
493 74 : ScFormulaCell* pFC = rDoc.GetFormulaCell(rPos);
494 74 : if (!pFC)
495 0 : return false;
496 :
497 74 : return pFC->GetErrCode() == 0;
498 : }
499 :
500 275 : OUString toString(
501 : ScDocument& rDoc, const ScAddress& rPos, ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram)
502 : {
503 275 : ScCompiler aComp(&rDoc, rPos, rArray);
504 275 : aComp.SetGrammar(eGram);
505 550 : OUStringBuffer aBuf;
506 275 : aComp.CreateStringFromTokenArray(aBuf);
507 550 : return aBuf.makeStringAndClear();
508 : }
509 :
510 151 : ScDocShellRef ScBootstrapFixture::load( bool bReadWrite,
511 : const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
512 : const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID,
513 : sal_uIntPtr nFilterVersion, const OUString* pPassword )
514 : {
515 : SfxFilter* pFilter = new SfxFilter(
516 : rFilter,
517 : OUString(), nFilterFlags, nClipboardID, rTypeName, 0, OUString(),
518 151 : rUserData, OUString("private:factory/scalc*"));
519 151 : pFilter->SetVersion(nFilterVersion);
520 :
521 151 : ScDocShellRef xDocShRef = new ScDocShell;
522 151 : xDocShRef->GetDocument()->EnableUserInteraction(false);
523 151 : SfxMedium* pSrcMed = new SfxMedium(rURL, bReadWrite ? STREAM_STD_READWRITE : STREAM_STD_READ );
524 151 : pSrcMed->SetFilter(pFilter);
525 151 : pSrcMed->UseInteractionHandler(false);
526 151 : if (pPassword)
527 : {
528 1 : SfxItemSet* pSet = pSrcMed->GetItemSet();
529 1 : pSet->Put(SfxStringItem(SID_PASSWORD, *pPassword));
530 : }
531 : SAL_INFO( "sc.qa", "about to load " << rURL );
532 151 : if (!xDocShRef->DoLoad(pSrcMed))
533 : {
534 3 : xDocShRef->DoClose();
535 : // load failed.
536 3 : xDocShRef.Clear();
537 : }
538 :
539 151 : return xDocShRef;
540 : }
541 :
542 54 : ScDocShellRef ScBootstrapFixture::load(
543 : const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
544 : const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID,
545 : sal_uIntPtr nFilterVersion, const OUString* pPassword )
546 : {
547 54 : return load( false, rURL, rFilter, rUserData, rTypeName, nFilterFlags, nClipboardID, nFilterVersion, pPassword );
548 : }
549 :
550 97 : ScDocShellRef ScBootstrapFixture::loadDoc(
551 : const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite )
552 : {
553 97 : OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
554 194 : OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
555 194 : OUString aFileName;
556 97 : createFileURL( rFileName, aFileExtension, aFileName );
557 194 : OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
558 97 : unsigned int nFormatType = aFileFormats[nFormat].nFormatType;
559 97 : unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
560 :
561 194 : return load(bReadWrite, aFileName, aFilterName, OUString(), aFilterType, nFormatType, nClipboardId, nFormatType);
562 : }
563 :
564 42 : const FileFormat* ScBootstrapFixture::getFileFormats()
565 : {
566 42 : return aFileFormats;
567 : }
568 :
569 318 : ScBootstrapFixture::ScBootstrapFixture( const OUString& rsBaseString ) : m_aBaseString( rsBaseString ) {}
570 318 : ScBootstrapFixture::~ScBootstrapFixture() {}
571 :
572 102 : void ScBootstrapFixture::createFileURL(
573 : const OUString& aFileBase, const OUString& aFileExtension, OUString& rFilePath)
574 : {
575 102 : OUString aSep("/");
576 204 : OUStringBuffer aBuffer( getSrcRootURL() );
577 102 : aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
578 102 : aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
579 204 : rFilePath = aBuffer.makeStringAndClear();
580 102 : }
581 :
582 40 : void ScBootstrapFixture::createCSVPath(const OUString& aFileBase, OUString& rCSVPath)
583 : {
584 40 : OUStringBuffer aBuffer( getSrcRootPath());
585 40 : aBuffer.append(m_aBaseString).append("/contentCSV/");
586 40 : aBuffer.append(aFileBase).append("csv");
587 40 : rCSVPath = aBuffer.makeStringAndClear();
588 40 : }
589 :
590 30 : ScDocShellRef ScBootstrapFixture::saveAndReload(
591 : ScDocShell* pShell, const OUString &rFilter,
592 : const OUString &rUserData, const OUString& rTypeName, sal_uLong nFormatType)
593 : {
594 :
595 30 : utl::TempFile aTempFile;
596 30 : aTempFile.EnableKillingFile();
597 60 : SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
598 30 : sal_uInt32 nExportFormat = 0;
599 30 : if (nFormatType == ODS_FORMAT_TYPE)
600 13 : nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
601 : SfxFilter* pExportFilter = new SfxFilter(
602 : rFilter,
603 : OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
604 30 : rUserData, OUString("private:factory/scalc*") );
605 30 : pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
606 30 : aStoreMedium.SetFilter(pExportFilter);
607 30 : pShell->DoSaveAs( aStoreMedium );
608 30 : pShell->DoClose();
609 :
610 : //std::cout << "File: " << aTempFile.GetURL() << std::endl;
611 :
612 30 : sal_uInt32 nFormat = 0;
613 30 : if (nFormatType == ODS_FORMAT_TYPE)
614 13 : nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
615 :
616 30 : ScDocShellRef xDocSh = load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat );
617 30 : if(nFormatType == XLSX_FORMAT_TYPE)
618 9 : validate(aTempFile.GetFileName(), test::OOXML);
619 21 : else if (nFormatType == ODS_FORMAT_TYPE)
620 13 : validate(aTempFile.GetFileName(), test::ODF);
621 60 : return xDocSh;
622 : }
623 :
624 30 : ScDocShellRef ScBootstrapFixture::saveAndReload( ScDocShell* pShell, sal_Int32 nFormat )
625 : {
626 30 : OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
627 60 : OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
628 30 : ScDocShellRef xDocSh = saveAndReload(pShell, aFilterName, OUString(), aFilterType, aFileFormats[nFormat].nFormatType);
629 :
630 30 : CPPUNIT_ASSERT(xDocSh.Is());
631 60 : return xDocSh;
632 : }
633 :
634 2 : void ScBootstrapFixture::miscRowHeightsTest( TestParam* aTestValues, unsigned int numElems )
635 : {
636 8 : for ( unsigned int index=0; index<numElems; ++index )
637 : {
638 6 : OUString sFileName = OUString::createFromAscii( aTestValues[ index ].sTestDoc );
639 : SAL_INFO( "sc.qa", "aTestValues[" << index << "] " << sFileName );
640 6 : int nImportType = aTestValues[ index ].nImportType;
641 6 : int nExportType = aTestValues[ index ].nExportType;
642 12 : ScDocShellRef xShell = loadDoc( sFileName, nImportType );
643 6 : CPPUNIT_ASSERT(xShell.Is());
644 :
645 6 : if ( nExportType != -1 )
646 4 : xShell = saveAndReload(&(*xShell), nExportType );
647 :
648 6 : CPPUNIT_ASSERT(xShell.Is());
649 :
650 6 : ScDocument* pDoc = xShell->GetDocument();
651 :
652 24 : for (int i=0; i<aTestValues[ index ].nRowData; ++i)
653 : {
654 18 : SCROW nRow = aTestValues[ index ].pData[ i].nStartRow;
655 18 : SCROW nEndRow = aTestValues[ index ].pData[ i ].nEndRow;
656 18 : SCTAB nTab = aTestValues[ index ].pData[ i ].nTab;
657 18 : int nExpectedHeight = aTestValues[ index ].pData[ i ].nExpectedHeight;
658 18 : if ( nExpectedHeight == -1 )
659 2 : nExpectedHeight = sc::TwipsToHMM( ScGlobal::GetStandardRowHeight() );
660 18 : bool bCheckOpt = ( ( aTestValues[ index ].pData[ i ].nCheck & CHECK_OPTIMAL ) == CHECK_OPTIMAL );
661 92 : for ( ; nRow <= nEndRow; ++nRow )
662 : {
663 : SAL_INFO( "sc.qa", " checking row " << nRow << " for height " << nExpectedHeight );
664 74 : int nHeight = sc::TwipsToHMM( pDoc->GetRowHeight(nRow, nTab, false) );
665 74 : if ( bCheckOpt )
666 : {
667 2 : bool bOpt = !(pDoc->GetRowFlags( nRow, nTab ) & CR_MANUALSIZE);
668 2 : CPPUNIT_ASSERT_EQUAL(aTestValues[ index ].pData[ i ].bOptimal, bOpt);
669 : }
670 74 : CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight);
671 : }
672 : }
673 6 : xShell->DoClose();
674 6 : }
675 20 : }
676 :
677 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|