/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
void testFormulaRefUpdateNameCopySheetCheckTab( const ScDocument* pDoc, SCTAB nTab, bool bCheckNames )
{ if (bCheckNames)
{ const ScRangeData* pName;
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"GLOBAL"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name GLOBAL should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"LOCAL"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name LOCAL should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"GLOBAL_GLOBAL"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name GLOBAL_GLOBAL should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"GLOBAL_LOCAL"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name GLOBAL_LOCAL should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"GLOBAL_UNUSED"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name GLOBAL_UNUSED should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"GLOBAL_UNUSED_NOREF"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name GLOBAL_UNUSED_NOREF should not exist", !pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"LOCAL_GLOBAL"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name LOCAL_GLOBAL should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"LOCAL_LOCAL"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name LOCAL_LOCAL should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"LOCAL_UNUSED"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name LOCAL_UNUSED should exist", pName);
pName = pDoc->GetRangeName(nTab)->findByUpperName(u"LOCAL_UNUSED_NOREF"_ustr);
CPPUNIT_ASSERT_MESSAGE("Sheet-local name LOCAL_UNUSED_NOREF should exist", pName);
}
ScRangeName* pGlobalNames = m_pDoc->GetRangeName();
ScRangeName* pSheetNames = m_pDoc->GetRangeName(0);
CPPUNIT_ASSERT_MESSAGE("Failed to obtain global named expression object.", pGlobalNames);
CPPUNIT_ASSERT_MESSAGE("Failed to obtain sheet-local named expression object.", pSheetNames);
for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
{
ScRangeData* pName = new ScRangeData(
*m_pDoc, OUString::createFromAscii(aNames[i].pName), OUString::createFromAscii(aNames[i].pExpr),
ScAddress(0,0,0), ScRangeData::Type::Name, formula::FormulaGrammar::GRAM_NATIVE);
if (aNames[i].bGlobal)
{ bool bInserted = pGlobalNames->insert(pName);
CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted);
} else
{ bool bInserted = pSheetNames->insert(pName);
CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bInserted);
}
}
// Artificially add external reference data after the context object is // initialized.
aCxt.maExternalFileNames.emplace_back("file:///path/to/fake.file");
std::vector<OUString> aExtTabNames;
aExtTabNames.emplace_back("Sheet");
aCxt.maExternalCachedTabNames.emplace(0, aExtTabNames);
ScAddress aPos(0,0,0);
for (size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i)
{ #if 0
OUString aFormula = OUString::createFromAscii(aTests[i]); #endif
ScCompiler aComp(*m_pDoc, aPos, FormulaGrammar::GRAM_ENGLISH); #if 0 // TODO: This call to CompileString() causes the cppunittester to somehow fail on Windows.
pArray.reset(aComp.CompileString(aFormula));
CPPUNIT_ASSERT_MESSAGE("Failed to compile formula string.", pArray.get());
CPPUNIT_TEST_FIXTURE(TestFormula, testFormulaParseReference)
{
OUString aTab1(u"90's Music"_ustr), aTab2(u"90's and 70's"_ustr), aTab3(u"All Others"_ustr), aTab4(u"NoQuote"_ustr);
m_pDoc->InsertTab(0, u"Dummy"_ustr); // just to shift the sheet indices...
m_pDoc->InsertTab(1, aTab1); // name with a single quote.
m_pDoc->InsertTab(2, aTab2); // name with 2 single quotes.
m_pDoc->InsertTab(3, aTab3); // name without single quotes.
m_pDoc->InsertTab(4, aTab4); // name that doesn't require to be quoted.
// Make sure the formula input and output match.
{ constchar* aChecks[] = { "='90''s Music'.B12", "='90''s and 70''s'.$AB$100", "='All Others'.Z$100", "=NoQuote.$C111"
};
for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
{ // Use the 'Dummy' sheet for this.
m_pDoc->SetString(ScAddress(0,0,0), OUString::createFromAscii(aChecks[i]));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong formula", OUString::createFromAscii(aChecks[i]), m_pDoc->GetFormula(0,0,0));
}
}
ScAddress aPos;
ScAddress::ExternalInfo aExtInfo;
ScRefFlags nRes = aPos.Parse(u"'90''s Music'.D10"_ustr, *m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(1), aPos.Tab());
CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(3), aPos.Col());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), aPos.Row());
CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
nRes = aPos.Parse(u"'90''s and 70''s'.C100"_ustr, *m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(2), aPos.Tab());
CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(2), aPos.Col());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(99), aPos.Row());
CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
nRes = aPos.Parse(u"'All Others'.B3"_ustr, *m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(3), aPos.Tab());
CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), aPos.Col());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), aPos.Row());
CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
nRes = aPos.Parse(u"NoQuote.E13"_ustr, *m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & ScRefFlags::VALID));
CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(4), aPos.Tab());
CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(4), aPos.Col());
CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), aPos.Row());
CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
// All numeric cells in Column A.
m_pDoc->SetValue(ScAddress(0,0,0), 1);
m_pDoc->SetValue(ScAddress(0,1,0), 2);
m_pDoc->SetValue(ScAddress(0,2,0), 3);
m_pDoc->SetValue(ScAddress(0,3,0), 4);
formula::VectorRefArray aArray = m_pDoc->FetchVectorRefArray(ScAddress(0,0,0), 4);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array is expected to be numeric cells only.", !aArray.mpStringArray);
CPPUNIT_ASSERT_EQUAL(1.0, aArray.mpNumericArray[0]);
CPPUNIT_ASSERT_EQUAL(2.0, aArray.mpNumericArray[1]);
CPPUNIT_ASSERT_EQUAL(3.0, aArray.mpNumericArray[2]);
CPPUNIT_ASSERT_EQUAL(4.0, aArray.mpNumericArray[3]);
aArray = m_pDoc->FetchVectorRefArray(ScAddress(0,0,0), 5);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array is expected to be numeric cells only.", !aArray.mpStringArray);
CPPUNIT_ASSERT_EQUAL(1.0, aArray.mpNumericArray[0]);
CPPUNIT_ASSERT_EQUAL(2.0, aArray.mpNumericArray[1]);
CPPUNIT_ASSERT_EQUAL(3.0, aArray.mpNumericArray[2]);
CPPUNIT_ASSERT_EQUAL(4.0, aArray.mpNumericArray[3]);
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 4));
// All string cells in Column B. Note that the fetched string arrays are // only to be compared case-insensitively. Right now, we use upper cased // strings to achieve case-insensitive-ness, but that may change. So, // don't count on that.
m_pDoc->SetString(ScAddress(1,0,0), u"Andy"_ustr);
m_pDoc->SetString(ScAddress(1,1,0), u"Bruce"_ustr);
m_pDoc->SetString(ScAddress(1,2,0), u"Charlie"_ustr);
m_pDoc->SetString(ScAddress(1,3,0), u"David"_ustr);
aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,0,0), 5);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array is expected to be string cells only.", !aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, u"Andy"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 1, u"Bruce"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 2, u"Charlie"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 3, u"David"_ustr));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 4));
// Mixture of numeric, string, and empty cells in Column C.
m_pDoc->SetString(ScAddress(2,0,0), u"Header"_ustr);
m_pDoc->SetValue(ScAddress(2,1,0), 11);
m_pDoc->SetValue(ScAddress(2,2,0), 12);
m_pDoc->SetValue(ScAddress(2,3,0), 13);
m_pDoc->SetString(ScAddress(2,5,0), u"=SUM(C2:C4)"_ustr);
m_pDoc->CalcAll();
aArray = m_pDoc->FetchVectorRefArray(ScAddress(2,0,0), 7);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should have both numeric and string arrays.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should have both numeric and string arrays.", aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, u"Header"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 1, 11));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 12));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 3, 13));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 4));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 5, 36));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 6));
// Mixed type again in Column D, but it starts with a numeric cell.
m_pDoc->SetValue(ScAddress(3,0,0), 10);
m_pDoc->SetString(ScAddress(3,1,0), u"Below 10"_ustr); // Leave 2 empty cells.
m_pDoc->SetValue(ScAddress(3,4,0), 11);
m_pDoc->SetString(ScAddress(3,5,0), u"=12"_ustr);
m_pDoc->SetString(ScAddress(3,6,0), u"=13"_ustr);
m_pDoc->SetString(ScAddress(3,7,0), u"=CONCATENATE(\"A\";\"B\";\"C\")"_ustr);
m_pDoc->CalcAll();
aArray = m_pDoc->FetchVectorRefArray(ScAddress(3,0,0), 8);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should have both numeric and string arrays.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should have both numeric and string arrays.", aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 0, 10));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 1, u"Below 10"_ustr));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 2));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 3));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 4, 11));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 5, 12));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 6, 13));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 7, u"ABC"_ustr));
// Column E consists of formula cells whose results are all numeric. for (SCROW i = 0; i <= 6; ++i)
m_pDoc->SetString(ScAddress(4,i,0), u"=ROW()"_ustr);
m_pDoc->CalcAll();
// This array fits within a single formula block.
aArray = m_pDoc->FetchVectorRefArray(ScAddress(4,0,0), 5);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should be purely numeric.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should be purely numeric.", !aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 0, 1));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 1, 2));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 3));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 3, 4));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 4, 5));
// This array spans over multiple blocks.
aArray = m_pDoc->FetchVectorRefArray(ScAddress(4,0,0), 11);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should have both numeric and string arrays.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should have both numeric and string arrays.", aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 0, 1));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 1, 2));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 3));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 3, 4));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 4, 5));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 5, 6));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 6, 7));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 7));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 8, u"Andy"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 9, 123));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 10));
// Hit the cache but at a different start row.
aArray = m_pDoc->FetchVectorRefArray(ScAddress(4,2,0), 3);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should at least have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 0, 3));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 1, 4));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 5));
// Column F begins with empty rows at the top.
m_pDoc->SetValue(ScAddress(5,2,0), 1.1);
m_pDoc->SetValue(ScAddress(5,3,0), 1.2);
m_pDoc->SetString(ScAddress(5,4,0), u"=2*8"_ustr);
m_pDoc->CalcAll();
aArray = m_pDoc->FetchVectorRefArray(ScAddress(5,2,0), 4);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should at least have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 0, 1.1));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 1, 1.2));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 16));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 3));
aArray = m_pDoc->FetchVectorRefArray(ScAddress(5,0,0), 3);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should at least have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 0));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 1));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 1.1));
aArray = m_pDoc->FetchVectorRefArray(ScAddress(5,0,0), 10);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should at least have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 0));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 1));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 2, 1.1));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 3, 1.2));
CPPUNIT_ASSERT_MESSAGE("Unexpected numeric cell.", equals(aArray, 4, 16));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 5));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 6));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 7));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 8));
CPPUNIT_ASSERT_MESSAGE("This should be empty.", isEmpty(aArray, 9));
// Get the array for F3:F4. This array should only consist of numeric array.
aArray = m_pDoc->FetchVectorRefArray(ScAddress(5,2,0), 3);
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
// Column G consists only of strings.
m_pDoc->SetString(ScAddress(6,0,0), u"Title"_ustr);
m_pDoc->SetString(ScAddress(6,1,0), u"foo"_ustr);
m_pDoc->SetString(ScAddress(6,2,0), u"bar"_ustr);
m_pDoc->SetString(ScAddress(6,3,0), u"foo"_ustr);
m_pDoc->SetString(ScAddress(6,4,0), u"baz"_ustr);
m_pDoc->SetString(ScAddress(6,5,0), u"quack"_ustr);
m_pDoc->SetString(ScAddress(6,6,0), u"beep"_ustr);
m_pDoc->SetString(ScAddress(6,7,0), u"kerker"_ustr);
aArray = m_pDoc->FetchVectorRefArray(ScAddress(6,1,0), 4); // G2:G5
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a numeric array.", !aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should have a string array.", aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, u"foo"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 1, u"bar"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 2, u"foo"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 3, u"baz"_ustr));
aArray = m_pDoc->FetchVectorRefArray(ScAddress(6,2,0), 4); // G3:G6
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a numeric array.", !aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should have a string array.", aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, u"bar"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 1, u"foo"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 2, u"baz"_ustr));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 3, u"quack"_ustr));
// Column H starts with formula cells. for (SCROW i = 0; i < 10; ++i)
m_pDoc->SetString(ScAddress(7,i,0), u"=ROW()"_ustr);
m_pDoc->CalcAll();
aArray = m_pDoc->FetchVectorRefArray(ScAddress(7,3,0), 3); // H4:H6
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, 4.0));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 1, 5.0));
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 2, 6.0));
aArray = m_pDoc->FetchVectorRefArray(ScAddress(7,4,0), 10); // H5:H15
CPPUNIT_ASSERT_MESSAGE("Failed to fetch vector ref array.", aArray.isValid());
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
CPPUNIT_ASSERT_MESSAGE("Unexpected string cell.", equals(aArray, 0, 5.0));
// Clear everything and start over.
clearRange(m_pDoc, ScRange(0,0,0,m_pDoc->MaxCol(),m_pDoc->MaxRow(),0));
m_pDoc->PrepareFormulaCalc();
// Totally empty range in a totally empty column (Column A).
aArray = m_pDoc->FetchVectorRefArray(ScAddress(0,0,0), 3); // A1:A3
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[0]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[1]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[2]));
// Totally empty range in a non-empty column (Column B).
m_pDoc->SetString(ScAddress(1,10,0), u"Some text"_ustr); // B11
aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,0,0), 3); // B1:B3
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[0]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[1]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[2]));
aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,12,0), 3); // B13:B15
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[0]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[1]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[2]));
// These values come from a cache because of the call above.
aArray = m_pDoc->FetchVectorRefArray(ScAddress(1,1,0), 3); // B2:B4
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray);
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[0]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[1]));
CPPUNIT_ASSERT(std::isnan(aArray.mpNumericArray[2]));
// The column begins with a string header at row 1 (Column C).
m_pDoc->SetString(ScAddress(2,0,0), u"MyHeader"_ustr); for (SCROW i = 1; i <= 9; ++i) // rows 2-10 are numeric.
m_pDoc->SetValue(ScAddress(2,i,0), i);
aArray = m_pDoc->FetchVectorRefArray(ScAddress(2,1,0), 9); // C2:C10
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray); for (size_t i = 0; i < 9; ++i)
CPPUNIT_ASSERT_EQUAL(double(i+1), aArray.mpNumericArray[i]);
// The column begins with a number, followed by a string then followed by // a block of numbers (Column D).
m_pDoc->SetValue(ScAddress(3,0,0), 0.0);
m_pDoc->SetString(ScAddress(3,1,0), u"Some string"_ustr); for (SCROW i = 2; i <= 9; ++i) // rows 3-10 are numeric.
m_pDoc->SetValue(ScAddress(3,i,0), i);
aArray = m_pDoc->FetchVectorRefArray(ScAddress(3,2,0), 8); // D3:D10
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray); for (size_t i = 0; i < 8; ++i)
CPPUNIT_ASSERT_EQUAL(double(i+2), aArray.mpNumericArray[i]);
// The column begins with a formula, followed by a string then followed by // a block of numbers (Column E).
m_pDoc->SetString(ScAddress(4,0,0), u"=1*2"_ustr);
m_pDoc->SetString(ScAddress(4,1,0), u"Some string"_ustr); for (SCROW i = 2; i <= 9; ++i) // rows 3-10 are numeric.
m_pDoc->SetValue(ScAddress(4,i,0), i*2);
aArray = m_pDoc->FetchVectorRefArray(ScAddress(4,2,0), 8); // E3:E10
CPPUNIT_ASSERT_MESSAGE("Array should have a numeric array.", aArray.mpNumericArray);
CPPUNIT_ASSERT_MESSAGE("Array should NOT have a string array.", !aArray.mpStringArray); for (size_t i = 0; i < 8; ++i)
CPPUNIT_ASSERT_EQUAL(double((i+2)*2), aArray.mpNumericArray[i]);
aDoubleRef.Extend(pDoc->GetSheetLimits(), aRef, ScAddress());
ScRange aTest = aDoubleRef.toAbs(*pDoc, ScAddress());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong start position of extended range.", ScAddress(2,2,0), aTest.aStart);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong end position of extended range.", ScAddress(6,5,0), aTest.aEnd);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong start position of extended range.", ScAddress(1,2,0), aTest.aStart);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong end position of extended range.", ScAddress(8,6,0), aTest.aEnd);
}
FormulaToken** ppTokens = pCode->GetCode(); for (sal_uInt16 i = 0; i < nLen; ++i)
{ const FormulaToken* p = ppTokens[i];
CPPUNIT_ASSERT_EQUAL(aCheckRPN[i].meOp, p->GetOpCode()); if (aCheckRPN[i].meOp != ocIf )
CPPUNIT_ASSERT_EQUAL(static_cast<int>(aCheckRPN[i].meType), static_cast<int>(p->GetType()));
}
// Generate RPN tokens again, but this time no jump command reordering.
pCode->DelRPN();
ScCompiler aCompRPN2(*m_pDoc, ScAddress(), *pCode, FormulaGrammar::GRAM_NATIVE);
aCompRPN2.EnableJumpCommandReorder(false);
aCompRPN2.CompileTokenArray();
staticconst TokenCheck aCheckRPN2[] =
{
{ ocPush, svSingleRef },
{ ocPush, svDouble },
{ ocPush, svString },
{ ocIf, svUnknown }, // type is context dependent, don't test it
};
nLen = pCode->GetCodeLen();
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong RPN token count.", static_cast<sal_uInt16>(SAL_N_ELEMENTS(aCheckRPN2)), nLen);
ppTokens = pCode->GetCode(); for (sal_uInt16 i = 0; i < nLen; ++i)
{ const FormulaToken* p = ppTokens[i];
CPPUNIT_ASSERT_EQUAL(aCheckRPN2[i].meOp, p->GetOpCode()); if (aCheckRPN[i].meOp == ocPush)
CPPUNIT_ASSERT_EQUAL(static_cast<int>(aCheckRPN2[i].meType), static_cast<int>(p->GetType()));
}
}
}
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of token(first argument to SUMIF)", svDoubleRef, ppTokens[0]->GetType());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of token(third argument to SUMIF)", svDoubleRef, ppTokens[2]->GetType());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong IsRel type for start column address in sum-range", rCase.bStartColRel, aSumRangeData.Ref1.IsColRel());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong IsRel type for end column address in sum-range", rCase.bEndColRel, aSumRangeData.Ref2.IsColRel());
}
}
}
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of raw token(argument to COS)", svDoubleRef, ppRawTokens[nRawArgPos]->GetType());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong type of RPN token(argument to COS)", svDoubleRef, ppRPNTokens[0]->GetType());
ScComplexRefData aArgRangeRaw = *ppRawTokens[nRawArgPos]->GetDoubleRef();
ScComplexRefData aArgRangeRPN = *ppRPNTokens[0]->GetDoubleRef(); bool bRawMatchRPNToken(aArgRangeRaw == aArgRangeRPN);
CPPUNIT_ASSERT_MESSAGE("raw arg token and RPN arg token contents do not match", bRawMatchRPNToken);
}
}
}
// Implicit intersection optimization in ScCompiler::HandleIIOpCode() internally changes // these to "=COS(A3)" and "=COS(A4)", but these shouldn't be merged into a formula group, // otherwise B4's formula would then be "=COS(A2:A6)".
CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula in B3 has changed.", u"=COS(A1:A5)"_ustr, m_pDoc->GetFormula(1,2,0));
CPPUNIT_ASSERT_EQUAL_MESSAGE("Formula in B4 has changed.", u"=COS(A1:A5)"_ustr, m_pDoc->GetFormula(1,3,0));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.