Assigning a user-defined type to a variant - an idea for better XData

Assigning a user-defined type to a variant - an idea for better XData

Anonymous
Not applicable
446 Views
5 Replies
Message 1 of 6

Assigning a user-defined type to a variant - an idea for better XData

Anonymous
Not applicable
Hi all,

To set the tone: I'm very experienced in VB, reasonably experienced in VBA,
and a newbie to AutoCAD (2002).

I like the idea of XData, but don't like the idea of having to remember what
thing is in what element (eg woodgrain is in XData(7)). So I had the idea
of using the XDataType 1004 (Binary Data) to hold a variant that holds a
user-defined type that I can structure however I like! (Notwithstanding the
127-byte limit for Binary data types.)

I tried something like this (simplified for this example):

Option Explicit

Private Type LineXDataType
AutoGenerated as Boolean
WoodStyle as Integer
End Type

Sub Whatever()
Dim LineObj(10) as AcadLine
Dim pt1(0 to 2) as Double, pt2(0 to 2) as Double
Dim XDataType(0 To 1) As Integer, XData(0 To 1) As Variant, LineXData As
LineXDataType

pt1(0) = 0: pt1(1) = 0: pt1(2) = 0
pt2(0) = 3: pt2(1) = 5: pt2(2) = 0
Set LineObj(1) = ThisDrawing.ModelSpace.AddLine(pt1, pt2)
LineXData.AutoGenerated = False
LineXData.WoodStyle = 3
XDataType(0) = 1001: XData(0) = "MyProject"
XDataType(1) = 1004: XData(1) = LineXData
LineObj(1).SetXData XDataType, XData
End Sub


However the compiler highlighted the statement "XData(1) = LineXData" and
gave the following error message:

Compile error: Only user-defined types defined in public object modules
can be coerced to or from a variant or passed to late-bound functions

Now I know that previously variants could not hold a user-defined type, but
that is supposedly no longer the case. Placing the cursor on the keyword
"Variant" in VBA and pressing F1 gives the help topic "Variant Data Type",
the second paragraph of which states:

A Variant is a special data type that can contain any kind of data
except fixed-length String data. (Variant types now support user-defined
types.)

So why am I getting this error? Based on the context of the error message I
tried moving the Type declaration and the Dim statements for the XData
variables to a module and making them Public but it didn't make any
difference.

If anyone can shed some insight as to what is happening here would have my
sincere appreciation.

Thanks

Wayne Ivory
Wespine Industries Pty Ltd
0 Likes
447 Views
5 Replies
Replies (5)
Message 2 of 6

Anonymous
Not applicable
I'm not even sure what you're trying to do is
possible, but if it is, it's not a wise thing
to do.

Let's suppose for a moment, that your program is
written and currently in use, and at some point,
it becomes necessary to add some additional data
or change the format of the existing persistent
data that you store in each entity's Xdata.

In that case, there may be cases where a drawing
will contain entities with Xdata that contain older
versions of the data structure. Given that, how
would you propose detecting which version of the
data structure is stored in the binary data that's
attached to each entity?

Furthermore, if you change the structure of your
user-defined data type, it will become impossible
to read existing data written using older versions
of the same data structure.

And, here is what you will end up having to do:

Private Type LineXDataType
AutoGenerated as Boolean
WoodStyle as Integer
End Type

' First revision of your application
' adds one persistent field

Private Type LineXDataType2
AutoGenerated as Boolean
WoodStyle as Integer
SomeNewField1 As SomeType
End Type

' Second revision of your application
' adds another persistent field

Private Type LineXDataType3
AutoGenerated as Boolean
WoodStyle as Integer
SomeNewField1 As SomeType
SomeNewField2 As SomeOtherType
End Type

Because what you are proposing to do breaks a basic
rule of software engineering (data binding), you may
be forced to use different user-defined types for
each revision of your persistent data format, and
that will in-turn, require you to revise every other
part of your code that uses those types, even if the
code is not directly affected by the change in the
persistent data format.

Can you see where this is going ?

By making the format of your persistent data
opaque, you also surrender the ability to easily
manage and handle multiple versions of your data
structure, which means that you will be setting
yourself up for major problems if you must change
the format of your persistent data in the future.

My advice is to forget about storing your data
structure in the entity in binary format. Instead,
create a reader and writer function that takes an
instance of your data structure, and an entity,
and reads/writes data between the XData and your
data structure.

If you do this, then you will have only two functions
that must deal with the format of the XData, and the
balance of your code doesn't have to know anything
about how the data is stored in the Entity.

More importantly, this will allow you to revise the
format of the persistent data, and deal with the
change without a major upheaval of your code, since
it will only require you to revise the reader function
to detect and handle newer versions of the data format,
and will allow you to use and revise a single user-
defined type.

In the writer function, include a version sentinel
as the first element in the Xdata (an integer or
short will do). That version sentinel can then be
used by the reader function to determine the version
of the data structure stored in each entity's Xdata,
so that if the structure of the persistent data were
to change in the future, the change can be handled
in a way that is transparent to the remainder of
your application.

"Wayne Ivory" wrote in message
news:C340F5B6E1346426BB9B6C8304459922@in.WebX.maYIadrTaRb...
> Hi all,
>
> To set the tone: I'm very experienced in VB, reasonably experienced in
VBA,
> and a newbie to AutoCAD (2002).
>
> I like the idea of XData, but don't like the idea of having to remember
what
> thing is in what element (eg woodgrain is in XData(7)). So I had the idea
> of using the XDataType 1004 (Binary Data) to hold a variant that holds a
> user-defined type that I can structure however I like! (Notwithstanding
the
> 127-byte limit for Binary data types.)
>
> I tried something like this (simplified for this example):
>
> Option Explicit
>
> Private Type LineXDataType
> AutoGenerated as Boolean
> WoodStyle as Integer
> End Type
>
> Sub Whatever()
> Dim LineObj(10) as AcadLine
> Dim pt1(0 to 2) as Double, pt2(0 to 2) as Double
> Dim XDataType(0 To 1) As Integer, XData(0 To 1) As Variant, LineXData
As
> LineXDataType
>
> pt1(0) = 0: pt1(1) = 0: pt1(2) = 0
> pt2(0) = 3: pt2(1) = 5: pt2(2) = 0
> Set LineObj(1) = ThisDrawing.ModelSpace.AddLine(pt1, pt2)
> LineXData.AutoGenerated = False
> LineXData.WoodStyle = 3
> XDataType(0) = 1001: XData(0) = "MyProject"
> XDataType(1) = 1004: XData(1) = LineXData
> LineObj(1).SetXData XDataType, XData
> End Sub
>
>
> However the compiler highlighted the statement "XData(1) = LineXData" and
> gave the following error message:
>
> Compile error: Only user-defined types defined in public object
modules
> can be coerced to or from a variant or passed to late-bound functions
>
> Now I know that previously variants could not hold a user-defined type,
but
> that is supposedly no longer the case. Placing the cursor on the keyword
> "Variant" in VBA and pressing F1 gives the help topic "Variant Data Type",
> the second paragraph of which states:
>
> A Variant is a special data type that can contain any kind of data
> except fixed-length String data. (Variant types now support user-defined
> types.)
>
> So why am I getting this error? Based on the context of the error message
I
> tried moving the Type declaration and the Dim statements for the XData
> variables to a module and making them Public but it didn't make any
> difference.
>
> If anyone can shed some insight as to what is happening here would have my
> sincere appreciation.
>
> Thanks
>
> Wayne Ivory
> Wespine Industries Pty Ltd
>
>
>
0 Likes
Message 3 of 6

Anonymous
Not applicable
Thanks for your comprehensive reply Tony. Everything you say is true,
however the nature of what I'm doing is such that the points you raise are
not an issue for me. The XData that I intend to use in this code will only
"live" for the duration of the code execution, ie as soon as the code
finishes the drawing will be complete and the XData will no longer be
needed. I'm only using it as a means for the code to keep track of a few
things while it is running. I could (and am currently since I can't get the
XData working) run parallel simple variables alongside the object variables
to keep track of all the stuff but this seems inefficient when I
theoretically can store stuff with it's related object.

So to reiterate, if you or anyone else can explain why VBA won't let the
variant receive the user-defined type in my example I'd be very
appreciative.

Thanks

Wayne Ivory
Wespine Industries Pty Ltd


"Tony Tanzillo" wrote in message
news:5A0E43DBC294B663140AF3B869E33B19@in.WebX.maYIadrTaRb...
> I'm not even sure what you're trying to do is
> possible, but if it is, it's not a wise thing
> to do.
>
.
.
.
0 Likes
Message 4 of 6

Anonymous
Not applicable
Wayne, I don't exactly have an answer for your XData question. It looks to
me like the documentation may be incorrect. However it seems like using
XData to hold data that you do not need to persist longer than code
execution is unnecessary. Why not just define a class with properties for
information you want to store? Just now I'm wondering if you created your
type in a class and tried to coerece it into a variant as a property of the
class if it would work... just a thought, but again I'd just drop the whole
XData issue and go with the class.

Regards,
Jacob Dinardi

"Wayne Ivory" wrote in message
news:F29E36D716226A1F48B73D6B0859DA19@in.WebX.maYIadrTaRb...
> Thanks for your comprehensive reply Tony. Everything you say is true,
> however the nature of what I'm doing is such that the points you raise are
> not an issue for me. The XData that I intend to use in this code will
only
> "live" for the duration of the code execution, ie as soon as the code
> finishes the drawing will be complete and the XData will no longer be
> needed. I'm only using it as a means for the code to keep track of a few
> things while it is running. I could (and am currently since I can't get
the
> XData working) run parallel simple variables alongside the object
variables
> to keep track of all the stuff but this seems inefficient when I
> theoretically can store stuff with it's related object.
>
> So to reiterate, if you or anyone else can explain why VBA won't let the
> variant receive the user-defined type in my example I'd be very
> appreciative.
>
> Thanks
>
> Wayne Ivory
> Wespine Industries Pty Ltd
>
>
> "Tony Tanzillo" wrote in message
> news:5A0E43DBC294B663140AF3B869E33B19@in.WebX.maYIadrTaRb...
> > I'm not even sure what you're trying to do is
> > possible, but if it is, it's not a wise thing
> > to do.
> >
> .
> .
> .
>
>
>
0 Likes
Message 5 of 6

Anonymous
Not applicable
"Wayne Ivory" wrote in message
news:F29E36D716226A1F48B73D6B0859DA19@in.WebX.maYIadrTaRb...
> Thanks for your comprehensive reply Tony. Everything you say is true,
> however the nature of what I'm doing is such that the points you raise are
> not an issue for me. The XData that I intend to use in this code will
only
> "live" for the duration of the code execution, ie as soon as the code
> finishes the drawing will be complete and the XData will no longer be
> needed. I'm only using it as a means for the code to keep track of a few
> things while it is running. I could (and am currently since I can't get
the
> XData working) run parallel simple variables alongside the object
variables
> to keep track of all the stuff but this seems inefficient when I
> theoretically can store stuff with it's related object.

On the contrary. Storing information in memory or program variables
is vastly more efficient than storing it in XData.

XData is stored in a drawing. Modifying it is just like modifying
any other entity data, and that means that AutoCAD must store the
changes made to Xdata in the undo file (because changes made to
Xdata is "undoable" just like any other entity data).

While you may not see all that is going on behind the scenes when
you write Xdata to a drawing, trust me when I tell you that it is
certainly *NOT* efficient, in contrast to doing the same using
in-memory program variables.

Unless you actually want your entity specific data to be 'undoable',
along with other changes to the entity (which may be a legitimate
requirement), then doing it in memory is far more efficient than
using XData.

If your data is entity specific, then consider a collection of a
class that includes a data member that ties each instance of the
class to a given entity (perhaps using its object id). That would
be far more efficient than the use of XData.
0 Likes
Message 6 of 6

Anonymous
Not applicable
Thanks Jacob and Tony. I've been using Visual Basic since the VB3 days
which was before classes. I've managed to avoid having to teach myself
about them up until now but it seems I have to pull my finger out now which
is probably a good thing. Thanks for the push in the right direction.

Regards

Wane Ivory
Wespine Industries Pty Ltd

"Tony Tanzillo" wrote in message
news:2F68B432D960A71652AA72364A274F1E@in.WebX.maYIadrTaRb...
> "Wayne Ivory" wrote in message
> news:F29E36D716226A1F48B73D6B0859DA19@in.WebX.maYIadrTaRb...
> > Thanks for your comprehensive reply Tony. Everything you say is true,
> > however the nature of what I'm doing is such that the points you raise
are
> > not an issue for me. The XData that I intend to use in this code will
> only
> > "live" for the duration of the code execution, ie as soon as the code
> > finishes the drawing will be complete and the XData will no longer be
> > needed. I'm only using it as a means for the code to keep track of a
few
> > things while it is running. I could (and am currently since I can't get
> the
> > XData working) run parallel simple variables alongside the object
> variables
> > to keep track of all the stuff but this seems inefficient when I
> > theoretically can store stuff with it's related object.
>
> On the contrary. Storing information in memory or program variables
> is vastly more efficient than storing it in XData.
>
> XData is stored in a drawing. Modifying it is just like modifying
> any other entity data, and that means that AutoCAD must store the
> changes made to Xdata in the undo file (because changes made to
> Xdata is "undoable" just like any other entity data).
>
> While you may not see all that is going on behind the scenes when
> you write Xdata to a drawing, trust me when I tell you that it is
> certainly *NOT* efficient, in contrast to doing the same using
> in-memory program variables.
>
> Unless you actually want your entity specific data to be 'undoable',
> along with other changes to the entity (which may be a legitimate
> requirement), then doing it in memory is far more efficient than
> using XData.
>
> If your data is entity specific, then consider a collection of a
> class that includes a data member that ties each instance of the
> class to a given entity (perhaps using its object id). That would
> be far more efficient than the use of XData.
>
>
>
>
>
0 Likes