LibreOffice Module test (master) 1
xspreadsheets2.cxx
Go to the documentation of this file.
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
11
12#include <com/sun/star/beans/XPropertySet.hpp>
13#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
14#include <com/sun/star/sheet/XSpreadsheet.hpp>
15#include <com/sun/star/sheet/XSpreadsheets2.hpp>
16#include <com/sun/star/sheet/XNamedRanges.hpp>
17#include <com/sun/star/sheet/XNamedRange.hpp>
18#include <com/sun/star/table/XCell.hpp>
19#include <com/sun/star/text/XTextRange.hpp>
20#include <com/sun/star/container/XIndexAccess.hpp>
21
22#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
23#include <com/sun/star/container/XNameContainer.hpp>
24#include <com/sun/star/table/CellVertJustify.hpp>
25#include <com/sun/star/util/XCloseable.hpp>
26
27#include <rtl/ustring.hxx>
28#include <cppunit/TestAssert.h>
29#include <o3tl/string_view.hxx>
30
31using namespace css;
32using namespace css::uno;
33
34namespace apitest {
35
36constexpr OUStringLiteral gaSrcSheetName(u"SheetToCopy");
37constexpr OUStringLiteral gaSrcFileName(u"rangenamessrc.ods");
38constexpr OUStringLiteral gaDestFileBase(u"ScNamedRangeObj.ods");
39
40static sal_Int32 nInsertedSheets(0);
41
42
44{
45}
46
48{
49 if (xDestDoc.is())
50 {
51 uno::Reference<util::XCloseable> xCloseable(xDestDoc, UNO_QUERY_THROW);
52 xCloseable->close(true);
53 }
54}
55
57{
63
64 uno::Reference< container::XNameAccess > xDestSheetNameAccess(xDestDoc->getSheets(), UNO_QUERY_THROW);
65 CPPUNIT_ASSERT_MESSAGE("Wrong sheet name", xDestSheetNameAccess->hasByName(gaSrcSheetName));
66
67}
68
70{
75
76 uno::Reference< table::XCell > xSrcCell = xSrcSheet->getCellByPosition(0,0);
77 uno::Reference< text::XTextRange > xSrcTextRange(xSrcCell, UNO_QUERY_THROW);
78 OUString aSrcString = xSrcTextRange->getString();
79
80 uno::Reference< table::XCell > xDestCell = xDestSheet->getCellByPosition(0,0);
81 uno::Reference< text::XTextRange > xDestTextRange(xDestCell, UNO_QUERY_THROW);
82 OUString aDestString = xDestTextRange->getString();
83
84 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong string imported", aSrcString, aDestString);
85}
86
88{
93
94 uno::Reference< table::XCell > xSrcCell = xSrcSheet->getCellByPosition(1,0);
95 sal_Int32 aSrcValue = xSrcCell->getValue();
96
97 uno::Reference< table::XCell > xDestCell = xDestSheet->getCellByPosition(1,0);
98 sal_Int32 aDestValue = xDestCell->getValue();
99
100 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong value imported", aSrcValue, aDestValue);
101}
102
104{
109
110 uno::Reference< table::XCell > xSrcCell = xSrcSheet->getCellByPosition(2,0);
111 OUString aSrcFormula = xSrcCell->getFormula();
112
113 uno::Reference< table::XCell > xDestCell = xDestSheet->getCellByPosition(2,0);
114 OUString aDestFormula = xDestCell->getFormula();
115
116 // potential problem later: formulas might be adjusted
117 // add some tests that the formulas are correctly adjusted
118 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula imported", aSrcFormula, aDestFormula);
119}
120
122{
127
128 uno::Reference< table::XCell > xSrcCell = xSrcSheet->getCellByPosition(3,0);
129 OUString aSrcFormula = xSrcCell->getFormula();
130
131 uno::Reference< table::XCell > xDestCell = xDestSheet->getCellByPosition(3,0);
132 OUString aDestFormula = xDestCell->getFormula();
133
134 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong Namedrange formula imported", aSrcFormula, aDestFormula);
135}
136
138{
147
148 uno::Reference< container::XNameAccess > xDestNamedRangesNameAccess(getNamedRanges(xDestDoc), UNO_QUERY_THROW);
149 uno::Any aNr = xDestNamedRangesNameAccess->getByName("initial1");
150 uno::Reference< sheet::XNamedRange > xDestNamedRange(aNr, UNO_QUERY_THROW);
151 OUString aNrDestContent = xDestNamedRange->getContent();
152
153 std::cout << "testImportSheet : initial1 aNrDestContent " << aNrDestContent << std::endl;
154 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong address for initial1", OUString("$Sheet1.$B$1"), aNrDestContent);
155
156}
157
159{
166
167 // New range name defined in imported sheet $SheetToCopy.$A$7
168 OUString aNewInSheetNamedRangeString("InSheetRangeName");
169 uno::Reference< container::XNameAccess > xDestNamedRangesNameAccess(getNamedRanges(xDestDoc), UNO_QUERY_THROW);
170 CPPUNIT_ASSERT_MESSAGE("InSheetRangeName", xDestNamedRangesNameAccess->hasByName(aNewInSheetNamedRangeString));
171
172 uno::Any aNewInSheetNr = xDestNamedRangesNameAccess->getByName(aNewInSheetNamedRangeString);
173 uno::Reference< sheet::XNamedRange > xDestNewInSheetNamedRange(aNewInSheetNr, UNO_QUERY_THROW);
174 OUString aNewInSheetNrDestContent = xDestNewInSheetNamedRange->getContent();
175 OUString aNewInSheetExpectedContent("$SheetToCopy.$A$7");
176
177 std::cout << "testImportSheet : InSheetRangeName content " << aNewInSheetNrDestContent << std::endl;
178 std::cout << "testImportSheet : InSheetRangeName expected " << aNewInSheetExpectedContent << std::endl;
179 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong address for InSheetRangeName", aNewInSheetExpectedContent, aNewInSheetNrDestContent);
180}
181
183{
190
191 // the source file redefines an existing named range in the imported sheet --> the target should not be changed
192 OUString aRedefinedInSheetNamedRangeString("initial2");
193 uno::Reference< container::XNameAccess > xDestNamedRangesNameAccess(getNamedRanges(xDestDoc), UNO_QUERY_THROW);
194 CPPUNIT_ASSERT_MESSAGE("aRedefinedInSheetNamedRangeString", xDestNamedRangesNameAccess->hasByName(aRedefinedInSheetNamedRangeString));
195
196 uno::Any aRedefinedInSheetNr = xDestNamedRangesNameAccess->getByName(aRedefinedInSheetNamedRangeString);
197 uno::Reference< sheet::XNamedRange > xDestRedefinedInSheetNamedRange(aRedefinedInSheetNr, UNO_QUERY_THROW);
198 OUString aRedefinedInSheetNrDestContent = xDestRedefinedInSheetNamedRange->getContent();
199 std::cout << "testImportSheet : initial2 content " << aRedefinedInSheetNrDestContent << std::endl;
200 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong address for Redefined InSheet named range", OUString("$Sheet1.$B$2"), aRedefinedInSheetNrDestContent);
201}
202
204{
211
212 //formula with a non-existent named range in dest - new_rangename
213 OUString aNewNamedRangeString("new_rangename");
214 uno::Reference< container::XNameAccess > xDestNamedRangesNameAccess(getNamedRanges(xDestDoc), UNO_QUERY_THROW);
215 CPPUNIT_ASSERT_MESSAGE("New NamedRange not created", xDestNamedRangesNameAccess->hasByName(aNewNamedRangeString));
216
217 // verify the content of this new namedrange, pointing on $Sheet1.$B$1 in source. This address is already defined in target as NR content
218
219 uno::Any aNewNr = xDestNamedRangesNameAccess->getByName(aNewNamedRangeString);
220 uno::Reference< sheet::XNamedRange > xDestNewNamedRange(aNewNr, UNO_QUERY_THROW);
221 OUString aNewNrDestContent = xDestNewNamedRange->getContent();
222
223 OUString aNewExpectedContent("$Sheet1.$B$1");
224
225 std::cout << "testImportSheet : new_rangename aNewExpectedContent " << aNewExpectedContent << std::endl;
226 std::cout << "testImportSheet : new_rangename aNewNrDestContent " << aNewNrDestContent << std::endl;
227 CPPUNIT_ASSERT_MESSAGE("Wrong New NamedRange formula string value", isExternalReference(aNewNrDestContent, aNewExpectedContent));
228}
229
231{
240
241 uno::Reference< table::XCell > xSrcCell = xSrcSheet->getCellByPosition(3,0);
242 xDestSheet->getCellByPosition(3,0);
243
244 //new style created in dest
245 uno::Reference< beans::XPropertySet > xSrcCellPropSet (xSrcCell, UNO_QUERY_THROW);
246 static constexpr OUStringLiteral aCellProperty(u"CellStyle");
247 OUString aSrcStyleName;
248 CPPUNIT_ASSERT(xSrcCellPropSet->getPropertyValue(aCellProperty) >>= aSrcStyleName);
249
250 uno::Reference< beans::XPropertySet > xDestCellPropSet (xSrcCell, UNO_QUERY_THROW);
251 OUString aDestStyleName;
252 CPPUNIT_ASSERT(xDestCellPropSet->getPropertyValue(aCellProperty) >>= aDestStyleName);
253
254 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong imported Cell Style", aSrcStyleName, aDestStyleName);
255
256 uno::Reference< style::XStyleFamiliesSupplier > xFamiliesSupplier (xDestDoc, UNO_QUERY_THROW);
257 uno::Reference< container::XNameAccess > xFamiliesNameAccess (xFamiliesSupplier->getStyleFamilies(), UNO_SET_THROW);
258 uno::Any aCellStylesFamily = xFamiliesNameAccess->getByName("CellStyles");
259 uno::Reference< container::XNameContainer > xCellStylesFamilyNameAccess (aCellStylesFamily, UNO_QUERY_THROW);
260
261 CPPUNIT_ASSERT_MESSAGE("New cell style not present", xCellStylesFamilyNameAccess->hasByName(aDestStyleName));
262
263 uno::Any aCellStyle = xCellStylesFamilyNameAccess->getByName(aDestStyleName);
264 uno::Reference< beans::XPropertySet > xCellStyleProp (aCellStyle, UNO_QUERY_THROW);
265 sal_Int32 aVertJustify = 0;
266 CPPUNIT_ASSERT(xCellStyleProp->getPropertyValue("VertJustify") >>= aVertJustify);
267
268 CPPUNIT_ASSERT_EQUAL_MESSAGE("New style: VertJustify not set", table::CellVertJustify_CENTER, static_cast<table::CellVertJustify>(aVertJustify));
269}
270
272{
278 CPPUNIT_ASSERT(nInsertedSheets > 0);
279 constexpr sal_Int32 nCols = 7;
280
281 uno::Reference< container::XNameAccess> xSrcNameAccess(init(),UNO_QUERY_THROW);
282 xSrcSheet.set( xSrcNameAccess->getByName(gaSrcSheetName), UNO_QUERY_THROW);
283
284 OUString aSrcString[nCols];
285 for (sal_Int32 nCol=0; nCol < nCols; ++nCol)
286 {
287 uno::Reference< table::XCell > xSrcCell = xSrcSheet->getCellByPosition(nCol, 0);
288 uno::Reference< text::XTextRange > xSrcTextRange(xSrcCell, UNO_QUERY_THROW);
289 aSrcString[nCol] = xSrcTextRange->getString();
290 }
291 // The named range 'initial2' is already present in the destination
292 // document defined to $Sheet1.$B$2 and thus is not copied, pointing to
293 // "content2" instead.
294 aSrcString[6] = "content2";
295
297 CPPUNIT_ASSERT(xDestDoc.is());
298 uno::Reference< container::XIndexAccess > xDestSheetIndexAccess (xDestDoc->getSheets(), UNO_QUERY_THROW);
299 CPPUNIT_ASSERT( nInsertedSheets < xDestSheetIndexAccess->getCount());
300 for (sal_Int32 nSheet=0; nSheet < nInsertedSheets; ++nSheet)
301 {
302 xDestSheet.set( xDestSheetIndexAccess->getByIndex(nSheet), UNO_QUERY_THROW);
303 for (sal_Int32 nCol=0; nCol < nCols; ++nCol)
304 {
305 uno::Reference< table::XCell > xDestCell = xDestSheet->getCellByPosition(nCol, 0);
306 uno::Reference< text::XTextRange > xDestTextRange(xDestCell, UNO_QUERY_THROW);
307 OUString aDestString = xDestTextRange->getString();
308
309 if (nCol == 4 && aDestString == "Err:540")
310 // The created external reference to the source document not
311 // allowed may result in Err:540
312 continue;
313
314 OString aMessage("Imported result does not match, sheet " + OString::number(nSheet)
315 + " column " + OString::number(nCol));
316 CPPUNIT_ASSERT_EQUAL_MESSAGE( aMessage.getStr(), aSrcString[nCol], aDestString);
317 }
318 }
319}
320
321uno::Reference< sheet::XSpreadsheetDocument> XSpreadsheets2::getDoc(const OUString& aFileBase)
322{
323 uno::Reference< lang::XComponent > xComp = loadFromDesktop(aFileBase);
324 uno::Reference< sheet::XSpreadsheetDocument > xDoc(xComp, UNO_QUERY_THROW);
325 return xDoc;
326}
327
328uno::Reference< sheet::XNamedRanges> XSpreadsheets2::getNamedRanges(uno::Reference< sheet::XSpreadsheetDocument> const & xDoc)
329{
330 uno::Reference< beans::XPropertySet > xPropSet (xDoc, UNO_QUERY_THROW);
331 uno::Reference< sheet::XNamedRanges > xNamedRanges(xPropSet->getPropertyValue("NamedRanges"), UNO_QUERY_THROW);
332 return xNamedRanges;
333}
334
336{
337 uno::Reference< container::XNameAccess> xSrcNameAccess(init(),UNO_QUERY_THROW);
338 xSrcSheet.set( xSrcNameAccess->getByName(gaSrcSheetName), UNO_QUERY_THROW);
339
341 CPPUNIT_ASSERT(xDestDoc.is());
342
343 // import sheet
344 uno::Reference< sheet::XSpreadsheets2 > xDestSheets (xDestDoc->getSheets(), UNO_QUERY_THROW);
345 sal_Int32 nDestPos = 0;
346 sal_Int32 nDestPosEffective = xDestSheets->importSheet(xDocument, gaSrcSheetName, nDestPos);
347 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong sheet index", nDestPos, nDestPosEffective);
349
350 uno::Reference< container::XIndexAccess > xDestSheetIndexAccess (xDestDoc->getSheets(), UNO_QUERY_THROW);
351 xDestSheet.set( xDestSheetIndexAccess->getByIndex(nDestPosEffective), UNO_QUERY_THROW);
352}
353
354bool XSpreadsheets2::isExternalReference(std::u16string_view aDestContent, std::u16string_view aSrcContent )
355{
356 CPPUNIT_ASSERT(o3tl::starts_with(aDestContent, u"'file://"));
357
358 if (!o3tl::endsWithIgnoreAsciiCase(aDestContent, aSrcContent)) // same cell address
359 return false;
360 size_t nPos = aDestContent.find(gaSrcFileName);
361 return nPos != std::u16string_view::npos && nPos > 0; // contains source file name
362}
363
364}
365
366/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::sheet::XSpreadsheet > xSrcSheet
css::uno::Reference< css::sheet::XSpreadsheet > xDestSheet
static css::uno::Reference< css::sheet::XNamedRanges > getNamedRanges(css::uno::Reference< css::sheet::XSpreadsheetDocument > const &)
virtual css::uno::Reference< css::lang::XComponent > loadFromDesktop(const OUString &)=0
virtual css::uno::Reference< css::uno::XInterface > init()=0
static bool isExternalReference(std::u16string_view aDestContent, std::u16string_view aSrcContent)
void testImportNamedRangeRedefinedInSource()
css::uno::Reference< css::sheet::XSpreadsheetDocument > getDoc(const OUString &)
css::uno::Reference< css::sheet::XSpreadsheetDocument > xDocument
css::uno::Reference< css::sheet::XSpreadsheetDocument > xDestDoc
float u
sal_uInt16 nPos
static sal_Int32 nInsertedSheets(0)
constexpr OUStringLiteral gaSrcFileName(u"rangenamessrc.ods")
constexpr OUStringLiteral gaSrcSheetName(u"SheetToCopy")
constexpr OUStringLiteral gaDestFileBase(u"ScNamedRangeObj.ods")
bool endsWithIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2, std::u16string_view *rest=nullptr)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept