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