What am I missing ?
lcBasePath='x:\data\'
oFileStructureCollection=CREATEOBJECT('Collection')
USE lcBasePath + 'users' && 30 fields
COPY STRUCTURE EXTENDED TO tFileStru
USE ('tFileStru') EXCLUSIVE
SELECT('tFileStru')
SCAN
SCATTER NAME oXFld memo
oFileStructureCollection.Add(oXFld)
? oXFld.Field_Name
ENDSCAN
ZAP
FOR EACH oFld IN oFileStructureCollection && 30 items
? oFld.Field_Name
APPEND BLANK
GATHER NAME oFld MEMO
ENDFOR
? RECCOUNT() && 30
All of the records were added back in after the ZAP by looping over APPEND BLANK, yet none of the original field values were written back from the collection object "oFld".
I'm stumped?
Does the ? oFld.Field_Name
value show inside the FOR EACH
? You should also write out the value of the field after the GATHER
and see if it made it at that point.
Other than the values not actually being in the collection objects, I can't see a reason why this shouldn't work.
FWIW, you can use CursorToCollection() and CollectionToCursor() to pretty much do this without manually writing the conversion code.
+++ Rick ---
If you run my code, (just point at any dbf file) and see if the "tFileStru" table is filled in, I could rule out it is something to do with my environment.
I know about CursorToCollection() and CollectionToCursor but I'm puzzled by why this code does not work.
After additional testing and adding a question mark after the GATHER on the oFld.Field_Name property, the generated table showed Field_Name present. But none of the other fields existed. Additional testing, made oFld.Field_Type=oFld.Field_Type and it now was written into the table as well.
Just for the hell of it, I added an AMEMBERS(laFlds,oFld) before the APPEND BLANK. The return value from AMEMBERS is equal to zero. Yet in the Debugger, I see all the properties of oFld. Then just to try and understand better, I moved the AMEMBERS to after oFld.Field_Type=oFld.Field_Type. Guess what, AMEMBERS returned a property count of one!
Seems like the collection has a scope issue with SCATTER or the Collection.ADD() since AMEMBERS and GATHER both don't see the values until after an operation like x=x is preformed.
Can this be an undocumented feature of VFP ?
Interesting... FOR EACH causes the problem!
The following works:
CLEAR
lcBasePath='c:\data\'
oFileStructureCollection=CREATEOBJECT('Collection')
USE lcBasePath + 'users'
COPY STRUCTURE EXTENDED TO tFileStru
USE ('tFileStru') EXCLUSIVE
SELECT('tFileStru')
SCAN
SCATTER NAME oXFld memo
oFileStructureCollection.Add(oXFld)
* ? 'add: ' + oXFld.Field_Name
ENDSCAN
ZAP
FOR i = 1 TO oFileStructureCollection.Count
oFld=oFileStructureCollection.Item(i)
* ? 'before: '+ oFld.Field_Name
* lnMembers=AMEMBERS(laFlds,oFld)
* ? 'before: '+ oFld.Field_Name
* ? 'before: '+ oFld.Field_type
APPEND BLANK
GATHER NAME oFld
* ? 'after: '+ oFld.Field_Name
* ? 'after: '+ oFld.Field_type
ENDFOR
If you add FoxObject to the For Each expression, it might work. IOW
FOR EACH oFld IN oFileStructureCollection FoxObject
WOW - That works!
FOR EACH oFld IN oFileStructureCollection FoxObject
Un-FU... real!!
Thanks
Good to know, and you're welcome.
Yeah you should always use FOXOBJECT
when using FOR EACH
except when using COM objects.
This is one of those FoxPro late stage langugae brain farts (like XMLTOCURSOR and XMLADAPTER/SQLADAPTER crazy syntax conventions) that make no sense, but at least the workaround is easy. If I recall FOR EACH
uses COM objects, and FOXOBJECT
forces FoxPro objects. Besides being more reliable it's MUCH faster.
FWIW, I prefer to use array style syntax with collections precisely because of that and also because I can swap with wwCollection
and wwNameValueCollection
which don't work with FOR EACH
as that's a special concept designed only to work against FoxPro collections or COM collections. Just another FoxPro language afterthought.
+++ Rick ---