basic/qa/basic_coverage/test_format_function.bas |    5 ++
 basic/qa/basic_coverage/test_str_method.bas      |   41 +++++++++++++++++++++++
 basic/source/runtime/methods.cxx                 |   19 ++++++++--
 basic/source/sbx/sbxscan.cxx                     |   10 +++++
 4 files changed, 70 insertions(+), 5 deletions(-)

New commits:
commit f846899e0b6fc2ec9ab2b4a4f65d06549e3f0763
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri Sep 26 21:14:33 2025 +0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Mon Sep 29 10:25:20 2025 +0200

    tdf#168561: fix Str function implementation
    
    1. If a string is passed as argument, it is returned without any changes.
    For that, SbRtl_Str checks argument type, skipping processing for string.
    
    2. Non-negative numbers are preceded by a blank space.
    That already was implemented.
    
    3. Negative numbers are preceded by a minus sign.
    That was done incorrectly - a space was added for any number.
    
    4. Dates are converted into locale-dependent strings.
    That wasn't done at all - dates were converted to strings representing
    the serial date. A check is implemented SbxValue::Format, to handle this.
    
    Additionally, Format function was improved to handle such input without
    format string (taking into account that it handles strings that can be
    converted to numbers differently).
    
    Change-Id: I5ac0429950e4ea8bf69b0091502b4e6dc1f4957d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191549
    Reviewed-by: Mike Kaganski <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 92878d3216aeaf0e5131c0c3fa1f8dc9ce67b5b4)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191582
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/basic/qa/basic_coverage/test_format_function.bas 
b/basic/qa/basic_coverage/test_format_function.bas
index f72e504a2379..0492a51b8840 100644
--- a/basic/qa/basic_coverage/test_format_function.bas
+++ b/basic/qa/basic_coverage/test_format_function.bas
@@ -39,6 +39,11 @@ Sub verify_testFormat
     TestUtil.AssertEqual(Format("abc", "1�5"), "abc", "Format(""abc"", 
""1�5"")")
     TestUtil.AssertEqual(Format("abc", "@ &"), "abc &", "Format(""abc"", ""@ 
&"")")
 
+    TestUtil.AssertEqual(Format(""), "", "Format("""")")
+    TestUtil.AssertEqual(Format(" "), " ", "Format("" "")")
+    TestUtil.AssertEqual(Format(" 00 "), "0", "Format("" 00 "")")
+    TestUtil.AssertEqual(Format(CDate("2025-09-26")), "09/26/2025", 
"Format(CDate(""2025-09-26""))")
+
     Exit Sub
 errorHandler:
     TestUtil.ReportErrorHandler("verify_testFormat", Err, Error$, Erl)
diff --git a/basic/qa/basic_coverage/test_str_method.bas 
b/basic/qa/basic_coverage/test_str_method.bas
new file mode 100644
index 000000000000..2ce10952ee04
--- /dev/null
+++ b/basic/qa/basic_coverage/test_str_method.bas
@@ -0,0 +1,41 @@
+' 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/.
+'
+
+Option Explicit
+
+Function doUnitTest as String
+    TestUtil.TestInit
+    verify_testStr
+    doUnitTest = TestUtil.GetResult()
+End Function
+
+Dim failedAssertion As Boolean, messages As String
+
+Sub verify_testStr
+    On Error GoTo errorHandler
+
+    ' If a string is passed as argument, it is returned without any changes
+    TestUtil.AssertEqualStrict(Str(""), "", "Str("""")")
+    TestUtil.AssertEqualStrict(Str(" "), " ", "Str("" "")")
+    TestUtil.AssertEqualStrict(Str(" 00 "), " 00 ", "Str("" 00 "")")
+
+    ' Non-negative numbers are preceded by a blank space
+    TestUtil.AssertEqualStrict(Str(0), " 0", "Str(0)")
+    TestUtil.AssertEqualStrict(Str(1 / 10), " 0.1", "Str(1 / 10)")
+
+    ' Negative numbers are preceded by a minus sign
+    TestUtil.AssertEqualStrict(Str(-1 / 10), "-0.1", "Str(-1 / 10)")
+
+    ' Dates are converted into locale-dependent strings (test uses en-US)
+    TestUtil.AssertEqualStrict(Str(CDate("2025-09-26")), "09/26/2025", 
"Str(CDate(""2025-09-26""))")
+
+    TestUtil.AssertEqualStrict(Str(true), "True", "Str(true)")
+
+    Exit Sub
+errorHandler:
+    TestUtil.ReportErrorHandler("verify_testStr", Err, Error$, Erl)
+End Sub
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index 679414e10a14..8598a9a522cf 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -1330,12 +1330,21 @@ void SbRtl_Str(StarBASIC *, SbxArray & rPar, bool)
     }
 
     OUString aStr;
-    OUString aStrNew(u""_ustr);
+    OUString aStrNew;
     SbxVariableRef pArg = rPar.Get(1);
-    pArg->Format( aStr );
+    const SbxDataType argType = pArg->GetType();
+    if (argType == SbxSTRING)
+    {
+        // From Help: "If a string is passed as argument, it is returned 
without any changes"
+        aStr = pArg->GetOUString();
+    }
+    else
+    {
+        pArg->Format(aStr);
+    }
 
     // Numbers start with a space
-    if (pArg->GetType() != SbxBOOL && pArg->IsNumericRTL())
+    if (argType != SbxBOOL && argType != SbxSTRING && pArg->IsNumericRTL())
     {
         // replace commas by points so that it's symmetric to Val!
         aStr = aStr.replaceFirst( ",", "." );
@@ -1371,7 +1380,9 @@ void SbRtl_Str(StarBASIC *, SbxArray & rPar, bool)
         }
         else
         {
-            aStrNew = " " + aStr;
+            if (!aStr.startsWith("-"))
+                aStrNew = " ";
+            aStrNew += aStr;
         }
     }
     else
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
index df6e704299b8..ed332d6ff645 100644
--- a/basic/source/sbx/sbxscan.cxx
+++ b/basic/source/sbx/sbxscan.cxx
@@ -443,7 +443,10 @@ std::optional<double> StrToNumberIntl(const OUString& s,
                                       std::shared_ptr<SvNumberFormatter>& 
rpFormatter)
 {
     double ret;
-    if (SbxValue::ScanNumIntnl(s, ret) == ERRCODE_NONE)
+    sal_Int32 nLen = 0;
+    bool bHasNumber = false;
+    if (ImpScan(s, ret, o3tl::temporary(SbxDataType()), &nLen, &bHasNumber, 
true) == ERRCODE_NONE
+        && bHasNumber && nLen == s.getLength())
         return ret;
 
     // We couldn't detect a Basic-formatted number (including type characters 
& specific exponents).
@@ -552,6 +555,11 @@ void SbxValue::Format( OUString& rRes, const OUString* 
pFmt ) const
         rRes = SbxBasicFormater::BasicFormatNull(pFmt ? *pFmt : 
std::u16string_view{});
         return;
     }
+    if (eType == SbxDATE && !pFmt)
+    {
+        rRes = GetOUString();
+        return;
+    }
 
     std::shared_ptr<SvNumberFormatter> pFormatter;
     std::optional<double> number = GetNumberIntl(*this, rRes, pFormatter, pFmt 
!= nullptr);

Reply via email to