Diese Seite mit anderen teilen ...

Informationen zum Thema:
Forum:
WinDev Forum
Beiträge im Thema:
21
Erster Beitrag:
vor 4 Jahren, 8 Monaten
Letzter Beitrag:
vor 4 Jahren, 8 Monaten
Beteiligte Autoren:
Michael Drechsel, Peter Holemans, Paulo Oliveira, Bart VDE, GuenterP, Ned!, Piet van Zanten

[WD17] Number of Columns for an array of structures

Startbeitrag von Michael Drechsel am 21.11.2013 11:07

Hi,

how can I get this information for:

Test is struct
sName is string
dDate is date
end

MyArray is array of 5 Test

Number_of_Rows=MyArray..occurence

But how can I get the number of Columns ???

Arrayinfo() doesn´t work and shows always 0.

Antworten:

Probably you can get this information (number of members) using the GetDefinition function for the structure.
check Definition (Type of variable) in the help.

von Paulo Oliveira - am 21.11.2013 12:50
Maybe.

But I give up because I can´t get access for this type of arrays with

myarray[1][1].

The background:

I need a function to add all numeric array members from

myarray[2] till myarray[number of rows] into myaaray[1]

von Michael Drechsel - am 21.11.2013 12:56
Hi,

If you have an array of 5 "Test" you can access the members of your structure using:


Test is Structure
sName is string
dDate is date
End


For i = 1 to ArrayCount(MyArray)
MyArray:sName
MyArray:dDate
End


Maybe you could add a numeric value to your structure and add them up in the loop...


Test is Structure
sName is string
dDate is date
iNumber is int
End


For i = 2 to ArrayCount(MyArray)
MyArray[1]:iNumber += MyArray:iNumber
End


So you are adding all the numbers from array line 2 to array line 5, and storing it in array line 1.

Hope it helps!

Thanks
Ned!

von Ned! - am 21.11.2013 14:28
Hi Ned,

thx for your input. Yes, that could be possible.
But its pitty that we can´t get the number of the rows of such an array out of the box.
I tried to create a global procedure which works with many different arrays. Because I use a webservice all my data are in a array of structures (based on queries)

von Michael Drechsel - am 21.11.2013 14:33
Hi Michael,

is ArrayCount(MyArray) an option?

von GuenterP - am 21.11.2013 15:02
No, its the same as arrayinfo()

von Michael Drechsel - am 21.11.2013 15:19
As far as i can understand your problem is with the number of member of the structure not the number of row of the array, correct?

For such generic procedures why don't you try to Serialize/Deserialize the array to XML do your programming over the XML and move it back to the array.

von Paulo Oliveira - am 21.11.2013 15:24
Yes. I need exact the functionality that Ned describes at top of this thread in the second part.

I don´t know the number of rows or columns and not the members of the structure.

All that should be generic in a procedure.

von Michael Drechsel - am 21.11.2013 15:45
Hi Michael,

What about GetDefinition?

Regards,
Piet

von Piet van Zanten - am 21.11.2013 16:00
Hi Piet,

nope. It gives me always only the name and the numeric type (36)

I tried getdefinition(myarray) and also getdefinition(myarray[1]).

von Michael Drechsel - am 22.11.2013 07:42
Hi Michael,

It seems you are confusing multi-dimensional arrays and single dimensional arrays.
What you have defined is in fact a single dimensional array (although in your mind it may seem more like a Multi dimensional array)...

There are two completely different things.
What you have is an array with a complex type variable (e.g. structure/class/data source/...)...

In your case you should be able to access it directly by using something like:
memberval = array[x].membername...

The syntax array[x][y] can only be used for Multi-dimensional arrays of a single type.

Just my 2 cents,

Peter H.

von Peter Holemans - am 22.11.2013 08:59
Hi Peter,

thats clear. My Problem is that I want get the "membername" for a procedure which can handle all my structure-arrays.


memberval = array[x].membername...

von Michael Drechsel - am 22.11.2013 09:03
Hi Michael,

This should be possible using indirection...
Out of my head something like hereunder (not tested):

FUNCTION GetMemberValueFromArray(LET pArray, pArrayIndex is int, pMemberName is string)

IF 0 < pArrayIndex


von Peter Holemans - am 22.11.2013 10:15
Hi Pete,

again, I don´t know the "pMemberName" at runtime. I have 200 different structure arrays in my project and I need one global procedure that can add the numeric values from index 2-999 into index 1.

The background is: The user can run a report over all array members (=records) and a summary of them . I use the same report and before printing I sum all into array[1] and print it.

In the moment I wrote it down like:

for n=2 to myarray..occurence
myarray[1].numericfield+= myarray[n].numericfield

end

But its a pain if you have 100+ structure members.


But thanks

von Michael Drechsel - am 22.11.2013 10:33
Hi Michael,

This should also be possible using indirection in combination with GetDefinition and
testing on teh type of teh first member to make sure it is numeric.

I have other stuff to do, but will try to create a code sample that works later today.
I think a 10 line function should be able to do this...

Cheers,

Peter H.

von Peter Holemans - am 22.11.2013 10:39
Hi Michael,

Look at this code :

TCustomer is structure
name is string
address is string
NumberOne is int
NumberTwo is numeric
END
Customer is TCustomer
Member is Variable Description

Def is Définition
Def = GetDefinition(Customer)


FOR EACH Member OF Def
Trace(StringBuild("Member %1 is %2",Member.Name,Member.Définition..Name))
END

von Bart VDE - am 22.11.2013 11:55
Hi Bart,

you forgot my little nice array:

MyCustomerArray is array of 5 TCustomer

and that doesn´t work for me:

Def = GetDefinition(MyCustomerArray) or
Def = GetDefinition(MyCustomerArray[1])

von Michael Drechsel - am 22.11.2013 12:00
TCustomer is structure
name is string
address is string
NumberOne is int
NumberTwo is numeric
END
AnArray is array of TCustomer
C is TCustomer

C.name = "test1"
C.address = "Test1"
C.NumberOne = 1
C.NumberTwo = 1
ArrayAddLine(AnArray,C)

C.name = "test2"
C.address = "Test2"
C.NumberOne = 2
C.NumberTwo = 2
ArrayAdd(AnArray,C)


Member is Variable Description

Def is Définition

Def = ArrayInfo(AnArray,tiElementDefinition)

Total is int=0
FOR i=1 _TO_ AnArray..Occurrence
FOR EACH Member OF Def
IF Member.Définition..Name ~= "int" THEN

Total += {StringBuild("AnArray[%1].%2",i,Member.Name)}
END
END
END

Info(Total) //shows 3

von Bart VDE - am 22.11.2013 12:52
Hi Bart,

you are the programmer of the day. :hot:

Many thanks

von Michael Drechsel - am 22.11.2013 13:04
Hi Michael,

It seems you've got your solution... Here's my little code to set a member (the first in this case) dynamically in an array of structures:

1) Calling and testing code:

PROCEDURE CallingCode()
Mystruct is Structure
Mmbr01_int is int
Mmbr02_date is Date
Mmbr03_string is string
Mmbr04_num is numeric
END

ArrayOfStruct is array of Mystruct
StructInst is Mystruct
TargetValue is int = 999

FOR i = 1 TO 10
StructInst.Mmbr01_int = i
StructInst.Mmbr02_date = DateSys()
StructInst.Mmbr03_string = "Instance "+i
StructInst.Mmbr04_num = i
Add(ArrayOfStruct,StructInst)
END

FOR ALL Struct OF ArrayOfStruct
Trace(Struct.Mmbr01_int)
END

GenericSetFirstMemberInArrayOfStructure(ArrayOfStruct,TargetValue)

FOR ALL Struct OF ArrayOfStruct
Trace(Struct.Mmbr01_int)
END


2) The routine that dynamically can set a numeric member (the first in this case) in all elements of type structure in any array:

FUNCTION GenericSetFirstMemberInArrayOfStructure(pArray, pSetFirstMemberToVal is int)
//Local variables
StructDef is a Définition

WHEN EXCEPTION IN
//Is it an array
IF TypeVar(pArray) IN (wlArray, wlAssociativeArray) THEN
//Is there something in the array
IF ArrayCount(pArray) > 0 THEN
//Dynamically type a variable struct to the content of the array
let Struct = pArray[1]
//Get the definition and make sure it is a structure?
StructDef = GetDefinition(Struct)
IF StructDef..Type = wlStructure THEN
//Make sure teh first member is numeric
IF TypeVar({Struct,StructDef.Variable[1]..Name}) IN (wlInt, wlInt_1, wlInt_2, wlInt_4, wlInt_8, wlUnsignedInt_1, wlUnsignedInt_2, wlUnsignedInt_4, wlUnsignedInt_8, ...
wlNumeric, wlReal, wlReal_4, wlReal_8, wlCurrency, wlVariant) THEN
//Set the first member to the new value using indirection
FOR ALL Struct OF pArray
{Struct,StructDef.Variable[1]..Name} = pSetFirstMemberToVal
END
RESULT True
ELSE
RESULT False
END
END
ELSE
//Nothing to set
RESULT True
END
ELSE
RESULT False
END
DO
Trace(ExceptionInfo(errComplet))
ExceptionEnable()
RESULT False
END


Cheers,

Peter H.

von Peter Holemans - am 22.11.2013 14:09
Zur Information:
MySnip.de hat keinen Einfluss auf die Inhalte der Beiträge. Bitte kontaktieren Sie den Administrator des Forums bei Problemen oder Löschforderungen über die Kontaktseite.
Falls die Kontaktaufnahme mit dem Administrator des Forums fehlschlägt, kontaktieren Sie uns bitte über die in unserem Impressum angegebenen Daten.