Bug 147262 - CallByName() argument names does not match that of VBA
Summary: CallByName() argument names does not match that of VBA
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: BASIC (show other bugs)
Version:
(earliest affected)
Inherited From OOo
Hardware: All All
: medium normal
Assignee: Julien Nabet
URL:
Whiteboard: target:7.4.0 target:7.3.1
Keywords:
Depends on:
Blocks: Macro-StarBasic 114263 141474
  Show dependency treegraph
 
Reported: 2022-02-07 17:04 UTC by Alain Romedenne
Modified: 2022-10-21 12:06 UTC (History)
3 users (show)

See Also:
Crash report or crash signature:


Attachments
The VBA error screenshot (45.09 KB, image/png)
2022-02-08 07:23 UTC, Mike Kaganski
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alain Romedenne 2022-02-07 17:04:39 UTC
Description:
Basic function argument names can be used either by position either by name.
CallByName second argument name should be 'ProcName' instead of 'ProcedureName'

- VBA doc:
https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/callbyname-function
- libO Basic function signatures:
https://opengrok.libreoffice.org/xref/core/basic/source/runtime/stdobj.cxx


Steps to Reproduce:
Consider the following code:

Sub Main
	Const vbGet = 2, vbLet = 4, vbMethod = 1, vbSet = 8
	dim c As New Collection : c.Add(100, "first") : c.Add(101)
	MsgBox "collection count is "& CallByName(c, "Count", vbGet)
	MsgBox "collection count is "& CallByName(object:=c, ProcedureName:="Count", CallType:=vbGet)
End Sub


Actual Results:
MsgBox statements both display 2

Expected Results:
MsgBox 2nd statement should use 'ProcName' instead of 'ProcedureName'


Reproducible: Always


User Profile Reset: No



Additional Info:
See https://bugs.documentfoundation.org/show_bug.cgi?id=141474 for more information.
Comment 1 Alain Romedenne 2022-02-07 18:09:23 UTC
CallByName() Basic test unit is under way
Comment 2 Julien Nabet 2022-02-07 18:13:14 UTC
It's been like this since 8834a4391c31502aabe137834ed852aa6b620287 in 2010.

Mike/Andreas:
I noticed:
    142 { u"CallByName",                    SbxVARIANT,  3 | FUNCTION_,        SbRtl_CallByName           },
    143     arg(u"Object",        SbxOBJECT),
    144     arg(u"ProcedureName", SbxSTRING),
    145     arg(u"CallType",      SbxINTEGER),
    146 
(see 
https://opengrok.libreoffice.org/xref/core/basic/source/runtime/stdobj.cxx?r=af3316b6#144)

and more generally with git grep:
basctl/source/basicide/baside2.cxx:1128:                        if (GetEditorWindow().GetProcedureName(aCurrLine, sProcType, sProcName))
basctl/source/basicide/baside2.hxx:156:    bool            GetProcedureName(OUString const & rLine, OUString& rProcType, OUString& rProcName) const;
basctl/source/basicide/baside2b.cxx:768:    bool bFoundName = GetProcedureName(aLine, sProcType, sProcName);
basctl/source/basicide/baside2b.cxx:813:bool EditorWindow::GetProcedureName(OUString const & rLine, OUString& rProcType, OUString& rProcName) const
basic/source/runtime/methods1.cxx:125:    // 2. parameter is ProcedureName
basic/source/runtime/stdobj.cxx:144:    arg(u"ProcedureName", SbxSTRING),

I thought about changing method name to make it explicit.
Ok for you? (it doesn't seem to be in public API)
Comment 3 Alain Romedenne 2022-02-07 18:25:33 UTC
A possible Basic test unit can be:

Option Explicit
Option Compatible

Function doUnitTest() As String
    TestUtil.TestInit
    verify_CallByName
    doUnitTest = TestUtil.GetResult()
End Function

Sub verify_CallByName()
    Const vbGet = 2, vbLet = 4, vbMethod = 1, vbSet = 8

    On Error GoTo errorHandler

	' Basic modules are Objects 
	TestUtil.AssertEqual(CallByName(TestUtil, "failCount", vbGet), 0, "CallByName(TestUtil, ""failCount"", vbGet")
	TestUtil.AssertEqual(CallByName(TestUtil, "passCount", vbGet), 1, "CallByName(TestUtil, ""passCount"", vbGet")
	TestUtil.AssertEqual(CallByName(TestUtil, "GetResult", vbMethod), "OK", "CallByName(TestUtil, ""GetResult"", vbMethod")

	' A Collection instances or ClassModule instances are Objects too !
    Dim c As New Collection
    c.Add(100, "1st") : c.Add(101)	
	TestUtil.AssertEqual(CallByName(c,"Count", vbGet), 42, "CallByName(c,""Count"", vbGet)")
    c.Remove(2)
    TestUtil.AssertEqual(CallByName(callType:=vbGet, object:=c, procedureName:="Count"), 41, _
        "CallByName(callType:=vbGet, object:=c, procedureName:=""Count"")")

    Exit Sub
errorHandler:
    TestUtil.ReportErrorHandler("verify_CallByName", Err, Error$, Erl)
    Resume Next
End Sub
Comment 4 Mike Kaganski 2022-02-07 20:03:21 UTC
I am all for the change that improves compatibility, since the named arguments only make sense in compatibility mode. And you have identified the place to change correctly. And I confirm that typing 'CallByName(' in VBA suggests Object, ProcName, CallType, and Args, as documentation describes those *named arguments*.

But trying to run your code in Excel's VBA errors out with

> Compile error:
> Argument in ParamArray may not be named

and I don't know what it means in this case.
Comment 5 Julien Nabet 2022-02-07 20:25:51 UTC
Here's a patch for master branch:
https://gerrit.libreoffice.org/c/core/+/129646
Comment 6 Alain Romedenne 2022-02-08 07:12:24 UTC
(In reply to Mike Kaganski from comment #4)
> I am all for the change that improves compatibility, since the named
> arguments only make sense in compatibility mode. And you have identified the
> place to change correctly. And I confirm that typing 'CallByName(' in VBA
> suggests Object, ProcName, CallType, and Args, as documentation describes
> those *named arguments*.
> 
> But trying to run your code in Excel's VBA errors out with
> 
> > Compile error:
> > Argument in ParamArray may not be named
> 
> and I don't know what it means in this case.

I don't have a copy of msoffice.
Can you indicate which statement(s) raise such errors?
Comment 7 Mike Kaganski 2022-02-08 07:23:53 UTC
Created attachment 178133 [details]
The VBA error screenshot

(In reply to Alain Romedenne from comment #6)

The VBA IDE highlighted the problematic part.
Comment 8 Mike Kaganski 2022-02-08 07:25:10 UTC
(In reply to Mike Kaganski from comment #7)

Note that changing ProcedureName to ProcName doesn't change the behavior.
Comment 9 Commit Notification 2022-02-09 19:42:27 UTC
Julien Nabet committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/a555aa25bd17781b2828e13ac81456a45387284d

tdf#147262: CallByName() argument names does not match that of VBA

It will be available in 7.4.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 10 Julien Nabet 2022-02-09 19:48:31 UTC
Patch for 7.3 waiting for review here:
https://gerrit.libreoffice.org/c/core/+/129754
Comment 11 Commit Notification 2022-02-10 08:33:23 UTC
Julien Nabet committed a patch related to this issue.
It has been pushed to "libreoffice-7-3":

https://git.libreoffice.org/core/commit/bfb1aa23457425707aaa80c342820a25468df937

tdf#147262: CallByName() argument names does not match that of VBA

It will be available in 7.3.1.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 12 Commit Notification 2022-02-18 00:18:05 UTC
Alain Romedenne committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/help/commit/401fb641aff217c7c333ce71d22abcf575d3ed09

tdf#114263 tdf#141474 tdf#147262 CallByName() function new help page
Comment 13 Commit Notification 2022-03-30 07:05:01 UTC
Alain Romedenne committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/b9b9b3afde384d2e24dcbf9a60fa9ee227576114

tdf#114263 tdf#147262 CallByName() function LibO Basic test unit

It will be available in 7.4.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.
Comment 14 Alain Romedenne 2022-10-21 12:06:26 UTC
(In reply to Mike Kaganski from comment #8)
> (In reply to Mike Kaganski from comment #7)
> 
> Note that changing ProcedureName to ProcName doesn't change the behavior.

I assume the behaviour lies in the way LibO or VBA implement CallByName using C++

- libO declares 3 explicit keyword names: object, ProcName & callType
  then a varying list of optional arguments
- M$ implements ONLY a varying list of arguments which prevents the use of named arguments

PS: Using 'object' as named argument in the first place - as M$ defined it - while 'Object' is a Basic/VBA reserved word, is probably a M$ error.