diff options
-rw-r--r-- | basic/source/inc/runtime.hxx | 3 | ||||
-rw-r--r-- | basic/source/runtime/runtime.cxx | 33 | ||||
-rw-r--r-- | sc/qa/extras/macros-test.cxx | 28 | ||||
-rw-r--r-- | sc/qa/extras/testdocuments/tdf130307.ods | bin | 0 -> 8277 bytes |
4 files changed, 63 insertions, 1 deletions
diff --git a/basic/source/inc/runtime.hxx b/basic/source/inc/runtime.hxx index 73e56838e2aa..d09db071a1a9 100644 --- a/basic/source/inc/runtime.hxx +++ b/basic/source/inc/runtime.hxx @@ -34,6 +34,7 @@ #include <memory> #include <com/sun/star/lang/XComponent.hpp> #include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> #include <unotools/localedatawrapper.hxx> #include <o3tl/deleter.hxx> #include <o3tl/typed_flags_set.hxx> @@ -55,6 +56,7 @@ enum class ForType { EachArray, EachCollection, EachXEnumeration, + EachXIndexAccess, Error, }; @@ -74,6 +76,7 @@ struct SbiForStack { // for/next stack: std::unique_ptr<sal_Int32[]> pArrayUpperBounds; css::uno::Reference< css::container::XEnumeration > xEnumeration; + css::uno::Reference<css::container::XIndexAccess> xIndexAccess; SbiForStack() : pNext(nullptr) diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx index 9a2a79e349b5..5c27b84223f7 100644 --- a/basic/source/runtime/runtime.cxx +++ b/basic/source/runtime/runtime.cxx @@ -1196,14 +1196,22 @@ void SbiRuntime::PushForEach() } else if (SbUnoObject* pUnoObj = dynamic_cast<SbUnoObject*>(pObj)) { - // XEnumerationAccess? + // XEnumerationAccess or XIndexAccess? Any aAny = pUnoObj->getUnoAny(); + Reference<XIndexAccess> xIndexAccess; Reference< XEnumerationAccess > xEnumerationAccess; if( aAny >>= xEnumerationAccess ) { p->xEnumeration = xEnumerationAccess->createEnumeration(); p->eForType = ForType::EachXEnumeration; } + // tdf#130307 - support for each loop for objects exposing XIndexAccess + else if (aAny >>= xIndexAccess) + { + p->eForType = ForType::EachXIndexAccess; + p->xIndexAccess = xIndexAccess; + p->nCurCollectionIndex = 0; + } else if ( isVBAEnabled() && pUnoObj->isNativeCOMObject() ) { uno::Reference< script::XInvocation > xInvocation; @@ -3204,6 +3212,29 @@ void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 ) } break; } + // tdf#130307 - support for each loop for objects exposing XIndexAccess + case ForType::EachXIndexAccess: + { + SbiForStack* p = pForStk; + if (!p->xIndexAccess) + { + SbxBase::SetError(ERRCODE_BASIC_CONVERSION); + pForStk->eForType = ForType::Error; // terminate loop at the next iteration + } + else if (pForStk->nCurCollectionIndex < p->xIndexAccess->getCount()) + { + Any aElem = p->xIndexAccess->getByIndex(pForStk->nCurCollectionIndex); + pForStk->nCurCollectionIndex++; + SbxVariableRef xVar = new SbxVariable(SbxVARIANT); + unoToSbxValue(xVar.get(), aElem); + (*pForStk->refVar) = *xVar; + } + else + { + bEndLoop = true; + } + break; + } case ForType::Error: { // We are in Resume Next mode after failed loop initialization diff --git a/sc/qa/extras/macros-test.cxx b/sc/qa/extras/macros-test.cxx index 6c4c9e185521..759f416ae490 100644 --- a/sc/qa/extras/macros-test.cxx +++ b/sc/qa/extras/macros-test.cxx @@ -68,6 +68,7 @@ public: void testTdf90278(); void testTdf143582(); void testTdf144085(); + void testTdf130307(); void testMacroButtonFormControlXlsxExport(); CPPUNIT_TEST_SUITE(ScMacrosTest); @@ -97,6 +98,7 @@ public: CPPUNIT_TEST(testTdf90278); CPPUNIT_TEST(testTdf143582); CPPUNIT_TEST(testTdf144085); + CPPUNIT_TEST(testTdf130307); CPPUNIT_TEST(testMacroButtonFormControlXlsxExport); CPPUNIT_TEST_SUITE_END(); @@ -1057,6 +1059,32 @@ void ScMacrosTest::testTdf144085() xCloseable->close(true); } +void ScMacrosTest::testTdf130307() +{ + OUString aFileName; + createFileURL(u"tdf130307.ods", aFileName); + auto xComponent = loadFromDesktop(aFileName, "com.sun.star.sheet.SpreadsheetDocument"); + + css::uno::Any aRet; + css::uno::Sequence<css::uno::Any> aParams; + css::uno::Sequence<css::uno::Any> aOutParam; + css::uno::Sequence<sal_Int16> aOutParamIndex; + + SfxObjectShell::CallXScript( + xComponent, + "vnd.sun.Star.script:Standard.Module1.ForEachSheets?language=Basic&location=document", + aParams, aRet, aOutParamIndex, aOutParam); + + OUString aReturnValue; + aRet >>= aReturnValue; + + // Without the fix in place, this test would have crashed here + CPPUNIT_ASSERT_EQUAL(OUString("Sheet1Sheet2"), aReturnValue); + + css::uno::Reference<css::util::XCloseable> xCloseable(xComponent, css::uno::UNO_QUERY_THROW); + xCloseable->close(true); +} + void ScMacrosTest::testTdf144970() { OUString aFileName; diff --git a/sc/qa/extras/testdocuments/tdf130307.ods b/sc/qa/extras/testdocuments/tdf130307.ods Binary files differnew file mode 100644 index 000000000000..fc354cf2cb1e --- /dev/null +++ b/sc/qa/extras/testdocuments/tdf130307.ods |