COM: Table Manipulation in MS Word broken in recent AHK versions

Report problems with documented functionality
Pchief123
Posts: 4
Joined: 06 Feb 2021, 04:10

COM: Table Manipulation in MS Word broken in recent AHK versions

01 Apr 2024, 08:30

Working with Tables in MS Word through COM was fine in AHK v2.0.5 but has a problem in v2.0.10+.

Raising Error Code : 0x800A16E6 : "Item" is not a property
Source : Microsoft Word
Specifically: Tables

The sample code in the attachment demonstrates the problem (after extraction run the test.ahk file)
Attachments
sample.7z
(10.71 KiB) Downloaded 13 times
User avatar
flyingDman
Posts: 2817
Joined: 29 Sep 2013, 19:01

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

01 Apr 2024, 09:05

Post your code using the code brackets.
14.3 & 1.3.7
Pchief123
Posts: 4
Joined: 06 Feb 2021, 04:10

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

01 Apr 2024, 09:23

Code: Select all

wordApp := ComObject("Word.Application")
document := wordApp.Documents.Open(A_ScriptDir . "\a.docx")
try {
	document.Tables[1].Cell[1, 1].Range.Text := "Hello"
} catch Any as e {
	MsgBox e.Message . "`n"
		. e.What . "`n"
		. e.Extra
} finally {
	document.Save()
	document.Close()
	wordApp.Quit()
}
RussF
Posts: 1270
Joined: 05 Aug 2021, 06:36

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

01 Apr 2024, 09:46

Found this post while searching for the error code. Seems @flyingDman has run into it before. Perhaps it is related?

Russ
User avatar
flyingDman
Posts: 2817
Joined: 29 Sep 2013, 19:01

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

01 Apr 2024, 10:53

Yes. This is a related issue and I am still trying to figure out why Tables.item(1) works but not Tables(1) as it did in v1. Try it with this line:

Code: Select all

document.Tables.item(1).cell(2,2).range.text := "Hello"
14.3 & 1.3.7
lexikos
Posts: 9593
Joined: 30 Sep 2013, 04:07
Contact:

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

11 Apr 2024, 21:06

Tables is a property with no parameters. Item is a method.

document.Tables[1] is property retrieval. It is a single operation where a property Tables is invoked with parameter 1. How it is dispatched depends on the implementation of the object. I can offer some conjecture based on "Item" is not a property, which I believe will be accurate:
  • The object's implementation finds a property Tables. It was asked to retrieve a property, so this is good. If this property had parameters, it could be invoked directly. However, it does not have parameters, so instead the property's value is retrieved as t, then t[1] is invoked.
  • The default member of t is Item (it's a common convention, but technically the default member could have any name), so t[1] is an attempt to invoke t.Item[1].
  • As it tells you, Item is not a property, so t.Item[1] is not valid.
You might think that if document.Tables[1] retrieves Tables and then invokes .Item[1], document.Tables(1) should retrieve Tables and then invoke .Item(1). Past second-hand experience tells me that Office and MSHTML COM objects don't work this way. I suppose that this object's implementation throws an error because it finds a property Tables when it was looking for a method.

If you use (document.Tables)(1), AutoHotkey will invoke Tables as a property and then invoke the default method of the Tables collection, which I presume is Item. This avoids relying on the object itself to indirectly dispatch the Item method via the Tables property.

v1.1 was designed (but I think not documented) to allow ambiguity between properties and methods of COM objects, in line with the ambiguity permitted by languages like VB, where array indexing and property parameters use the same syntax as function/method calls. Due to that ambiguity and perhaps a lack of clear guidelines, COM objects from different libraries (even just Microsoft ones) ended up being inconsistent with each other; e.g. Item and _NewEnum are sometimes properties, sometimes methods.

v1.1 invokes with inconsistent combinations of the method and property flags depending on a number of undocumented factors. When both flags (method and property) are present, the Office and MSHTML COM objects may do things like retrieve the Tables property and then invoke its Item method, but COM objects which could and should distinguish between property retrieval and method call are unable to do so.

v2.0.6 was intended to fix some cases that were clearly incorrect, with the one documented example being "x.y acting as x.y()". In particular, if an object from another instance of AutoHotkey (v1 or v2) is accessed via COM, prior to v2.0.6 it was impossible to retrieve the value of a property if that value was a function, because the function was called automatically.

The change had more far-reaching consequences than I was expecting, but ultimately I decided to treat the previous behaviour as incorrect, even in cases like document.Tables(1) where VB examples would lead you to believe it should work. It is better to receive an error message like "Item is not a property" than to have some property's value unexpectedly called when it was meant to be retrieved, or similar occurrences. The kind of ambiguity permitted prior to v2.0.6 is not in keeping with the spirit of v2, or the defined meanings of each part of the syntax.

In other words, this is not a bug; you need to use the appropriate syntax for the property or method that you are invoking.
User avatar
flyingDman
Posts: 2817
Joined: 29 Sep 2013, 19:01

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

12 Apr 2024, 15:11

Thank you for shedding light on the intrinsic ambiguity between properties and methods in VBA and your decision to discontinue this ambiguity in v2. That said, for those like me who made extensive use of the MS VBA documentation to write AHK COM code, it has not become easier as certain things that were possible in VBA and in v1 - in particular for MS Word - are no longer possible in v2. E.g. there is no example in the VBA docs for the use of (document.Tables)(1) it is just document.Tables(1).
In the example here: viewtopic.php?f=82&t=128362&p=566781#p566706 , things get sketchier. To activate one of several open Word documents this works in v1 (and mirrors VBA):

Code: Select all

oWord := ComObjActive("word.application")
oWord.documents(1).activate
If I am correct the (only?) way to achieve the same in v2 is:

Code: Select all

oWord := ComObjActive("word.application")
doc := (oWord.documents)(1)    ; oWord.documents.item(1) also works
doc.activate                   ; this needs to be on a separate line!  (oWord.documents)(1).activate does not work
Because it requires these 2 tweaks, the learning curve has steepened.

On the other hand for Excel, this code still works fine in v2:

Code: Select all

xl := ComObjActive("excel.application")
xl.Workbooks(2).Activate	
msgbox xl.activeworkbook.name
So there appear to be inconsistencies between how v2 handles Word and Excel (and I assume this is because of MS rather than AHK).
14.3 & 1.3.7
Descolada
Posts: 1143
Joined: 23 Dec 2021, 02:30

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

13 Apr 2024, 01:54

@flyingDman AHK is not VBA, so you will definitely need to make some adjustments. Here I see two problems:
1) The Tables property does not have an item property that accepts arguments, and instead has the item method. Since AHK calls methods with the parenthesis syntax, you need to use parenthesis in one form or another. I would recommend using oWord.documents.item(1) as it explicitly shows you are using the item method.
2) AHK v2 allows omitting function parenthesis only if the function is used at the start of a line. oWord.application.documents.item(1).activate should work but instead throws an error. @lexikos is this expected behavior? oWord.application.documents.item 1 works fine on a separate line. In any case I'd suggest marking all your methods with parenthesis to lessen ambiguity (eg also use MyMenu.show() instead of MyMenu.show) and to avoid potential bugs in the future.

Code: Select all

#Requires AutoHotkey v2

oword := ComObjActive("Word.Application")
MyMenu := Menu()
loop oWord.documents.count
	MyMenu.Add(oWord.documents.item(a_index).name, MyMenuMenuHandler)
MyMenu.Check(oWord.activedocument.Name)							; puts a ✓ next to the active document
MyMenu.show()

MyMenuMenuHandler(ItemName, ItemPos, MyMenu) { 
    oWord.application.documents.item(ItemPos).activate()
    msgbox(oWord.activedocument.Name, "Active Doc is:")
}
lexikos
Posts: 9593
Joined: 30 Sep 2013, 04:07
Contact:

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

20 Apr 2024, 08:43

@Descolada I presume you are thinking that oWord.application.documents.item(1).activate should behave as though there was () at the end. Which part of the documentation tells you that it should work that way?

I assume the thrown error is due to activate being a method, while you are getting a property. I do not have Word.
Descolada
Posts: 1143
Joined: 23 Dec 2021, 02:30

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

20 Apr 2024, 09:17

lexikos wrote:
20 Apr 2024, 08:43
@Descolada I presume you are thinking that oWord.application.documents.item(1).activate should behave as though there was () at the end. Which part of the documentation tells you that it should work that way?
I am indeed thinking that, and no part of the documentation tells me that. The documentation doesn't tell me that oWord.application.documents.item 1 would work either, but it does. My thinking was that accessing a property (in this case item) at the start of the line and not doing anything with the output (eg assigning to a variable) wouldn't make sense and AHK allows calling functions in the same convention without parenthesis, so the method would be accessed preferentially, but the reality didn't match my expectations. Perhaps this behavior could be added, and/or the documentation changed appropriately?

Btw, I couldn't find in the documentation that function parenthesis can be omitted when at the start of the line either, I only found it mentioned in a comment in an example code snippet. Not sure if that can be counted as actually being part of the "official documentation".
lexikos
Posts: 9593
Joined: 30 Sep 2013, 04:07
Contact:

Re: COM: Table Manipulation in MS Word broken in recent AHK versions

23 Apr 2024, 03:57

@Descolada
Most of the language's syntax is documented on one page, creatively titled "Scripting Language". You need only search through occurrences of "parentheses", or read through the "Function Calls" section.

You may have observed that oWord...item 1 does work, but my point is that you can only know that it should work if you have read applicable documentation. If you haven't found documentation which proves that what you're doing is valid, then you could assume it isn't valid and use something else instead. Once you find the part of the documentation that tells you parentheses can be omitted in method calls, it is impossible to miss the restriction unless you stop reading mid-sentence.

Allowing an arbitrary expression rather than a name (run "...") or series of names (myGui.Add "Edit") would make it potentially much more difficult for a human to determine whether they are looking at a pure expression or a function/method call statement. The simple rule is easy to remember and easy to follow. Some cases where a user might be intending a method call could trigger warnings in future (like (a).b c where the result of the implicit concatenation is not used), but according to the current rules, (a).b would be a legitimate way to invoke a property for its side-effects.

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 16 guests