Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

The Use of Variants

Status
Not open for further replies.

CajunCenturion

Programmer
Mar 4, 2002
11,381
US
Thanks to [b[strongm[/b] for suggesting the following (much better) topic for discussion:

Should VB Programmers use Variants? Why or Why Not? Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
My opinion, avoid at all cost. I can see where it may be useful but I rarely use it. If you are trying to overload a procedure is about the only time I can think of using it. Here again, I believe this leads to sloppy coding and laziness. As with all "improvements" to make programming easier comes abuse. I believe that about 75% of the code that I have worked with that contains variants should have been written with a specific type variable. You can see what happen with the code, someone uses a variant type for conceptual testing, works the code to get the functionality desired and uses a variant type were a long could be used, never spending the time to update the code (what a waste of resources). Here again plays the "other peoples code" where an attempt to determine the logic of a procedure slammed with variants is really difficult to read were as specific types tend to allow you to at least assume what the code is expecting for data. That is enough for now, just figured I would get this started as well. If you choose to battle wits with the witless be prepared to lose.
[machinegun][hammer]
 
Cajun, I think everyone lost there opinions! [neutral] If you choose to battle wits with the witless be prepared to lose.
[machinegun][hammer]
 
foada, I guess
We had some good discussions a while back on OO vs Not OO, Programming Style, and we almost got a good one going on the Best Database. Was hoping to get something not too specific, where there's really no necessarily right and wrong answer - get some participation. That type of discussion, one that makes people think, can often have benefits. That type of interchange of ideas is one of the main purposes of Tek-Tips - not to just swap code.

=======================================================

For what is worth, the only time I use a variant in production programming is when extracting value from a recordset which may be null, before assigning them to some internal variable. Something like this

strVariable = GetString(RecSet.Fields("FieldName"))

Public Function GetString(rVar_InData As Variant) As String
If Not (IsNull(rVar_InData)) Then
GetString = Trim(CStr(rVar_InData))
Else
GetString = vbNullString ' vbNullString is better than "" - just ask foada !!!
End If
End Sub

(I also have GetValue, GetDate, GetLogical, etc functions)

That being said, I have been known to be a little lazy and use variants when doing some quick and dirty tests, or maybe a prototype to test viability, or some other type of throw away code. Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
I don't think people have lost their opinions, I think you've said it all!!

I agree that variants are confusing! I got so lost when I started with stuff like
Code:
dim sString, sAnotherString as string
'sString ain't a string!! it's a variant!

I don't like 'em. I go so far as to explicit cast/ convert whenever I need to. That way I have to think about what type each variable is!
Code:
dim nInt as integer
dim sString as string

nInt = 1
sString = "The Value of nInt is " & cstr(nInt)
' not
sString = "the Value of nInt is " & nInt
' nInt is coerced in to a string by & operator 
' I don't like implicit!!!

If you want opinions: I got em!

What about Hungarian notation? Is it good or what? I like it cos it tells me what type a variable is!

Hope this raises some controversy!

Matt
 
go for it matt - start the thread and lets see where it goes Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein
 
Just want to add a few points:

Variant is a data type that stores both a value and metadata specifying how the data should be interpreted. Variants are not variables without a data type but typed variables that can change their data type as needed.

Variants have their uses; specifically, in cases where a data type is unknown at compile time. (For example, ADO Recordset.Fields(<SomeField>) = ????. Due to a RecordSet's generic nature, it is not known what data type is returned.) Variants have their use, but should only be used when necessary.

They also provide a way of passing values between programs written using different compilers that might not share the same data types. Because metadata is passed along with a value, the interface layer can provide translation services between the two programs.

Again, use only when necessary...



Mark
 
Thought you all might be interested in the following. This is the declaration section of 1 class module in an application that I am currently rewritting (Guess Why and no prizes for the answer) !!!!

The section is actually over 15 pages (this is an extract)

Dim aNumberOfPacks() As Variant
Dim aPackageName() As Variant
Dim aNumberSubPacks() As Variant
Dim aSubPackName() As Variant
Dim aGrossWeight() As Variant
Dim aVolume() As Variant
Dim aVolumeUnit() As Variant
Dim aFK3610() As Integer
Dim aID0046() As Integer

Dim aDescriptionText() As Variant
Dim aFK0046_10() As Integer
Dim aMarksNumbers() As Variant
Dim aFK0046_20() As Integer

Dim aMinTemp() As Variant
Dim aMaxTemp() As Variant
Dim aTempSet() As Variant
Dim aTempQualifier() As Variant
Dim aTempUnit() As Variant
Dim aFK3610_39() As Integer
Dim aLength() As Variant
Dim aHeight() As Variant
Dim aWidth() As Variant
Dim aDimensionUnits() As Variant
Dim aVolume40() As Variant
Dim aVolumeUnits() As Variant
Dim aFK3610_40() As Integer

Dim aID0045() As Variant Dim aInvoiceNumber() As Variant
Dim aRNANumber() As Variant
Dim aSaleCurrency() As Variant 'currency field
Dim aIssuedCity() As Variant 'issued city
Dim aPrepaidCollect() As Variant 'prepaid collect field
Dim aDebtorName() As Variant
Dim aDebtorAdd1() As Variant
Dim aDebtorAdd2() As Variant
Dim aDebtorAdd3() As Variant
Dim aDebtorCity() As Variant
Dim aDebtorPostcode() As Variant
Dim aDebtorCountryCode() As Variant
Dim aDebtorCountryName() As Variant
Dim aCreatedOffice() As Variant


'only declared the ones for COREP52 as present
Dim aFK0045() As Variant 'foreign key to ID0045
Dim aTypeDescription() As Variant
Dim aTotalAmount() As Variant

'only declared the ones for COREP52 at present
Dim aPrepaidCollect47() As Variant
Dim aFreightCurrency() As Variant
Dim aAmount() As Variant

Dim aServiceType() As Variant
Dim aRevenueType() As Variant
Dim aChargeType() As Variant


Dim aOUCode() As Variant
Dim aOUName() As Variant
Dim aOUAddress1() As Variant
Dim aOUAddress2() As Variant
Dim aOUAddress3() As Variant
Dim aOUCity() As Variant
Dim aOUPostcode() As Variant
Dim aOUCountryName() As Variant
Dim aOUSubCountryName() As Variant

Dim aFTPOD() As Variant 'Footer text port of discharge
Dim aFTCountry() As Variant 'footer text originator country
Dim aFTTerminal() As Variant 'footer text destination terminal
Dim aFTExportOffice() As Variant 'footer text export office
Dim aFTBLType() As Variant 'footer text BL Type
Dim aFTFiller() As Variant 'footer text filler text
'array size will be (1 to 12,n) where n
'= each different entry. Array positions will correspond to Footer Text
'line #

Dim aSLC() As Variant 'shipping line code
Dim aSLCurrencyCode() As Variant 'SL Currency Code
Dim aPortROE() As Variant
Dim aSLVCRCurrencyCode() As Variant
Dim aCAUU() As Variant

Dim aHold() As Variant
Dim aCharges() As Variant 'notification charges

Public EmailAddress As Variant
Public MessageText As Variant
Public DisclaimerLn1 As Variant
Public DisclaimerLn2 As Variant 'V4.3.0 added


Public PARMCO2PrintProof As Boolean
Public PARMCO51FinalDemurDte As Variant
Public PARMCO51CustomsMark As Variant
Public PARMCO51ShipNat As Variant
Public PARMCO51RestDepot As Variant
Public PARMCO51ExpectedArrDte As Variant
Public PARMCO51ExpectedDelDte As Variant
Public PARMCO51ContactNme As Variant
Public PARMCO51TelExt As Variant

Public PARMCO2OriginalExpress As Boolean
Public PARMCO52NotNegotiable As Boolean

Public EUserMessage As Variant
Public ESystemsMessage As Variant

Oh how I love variants !!!!

Chris Dukes

 
Chris,

My sympathy goes out to you! What a mess. Good Luck. If you choose to battle wits with the witless be prepared to lose.
[machinegun][hammer]
 

The guess would be memory problems since a variant will take up more memory whether it holds a numeric or string value versus the counter parts(Int,Long,Double,String).

In defence of the variant because of poor planning of the VB designers the variant is good to use when you have a decimal or floating point value since VB does not have these data types. So you can cast a variant to hold your decimal i.e. variant = CDec(somevalue), but overall unless you really need a variant it is better to declare what your variable is (int,long,double,date,string, etc.)
 
here is just the general declarations of my modulus in a program I'm working on, this is a short part of the program:) the full program is about 100,000 lines of code with over 50 forms so it's pretty small:)!!!
As you can see I don't care for variants all that much!

Public mcnn As ADODB.Connection 'Connection string
Public usrs As ADODB.Recordset 'Users recordset
Public cors As ADODB.Recordset 'Company recordset
Public zprs As ADODB.Recordset 'Zip Code recordset
Public fzrs As ADODB.Recordset 'Foreign city/zip recordset
Public cncd As ADODB.Recordset 'Country codes recordset
Public nxno As ADODB.Recordset 'Next assigned number
Public cntl As ADODB.Recordset 'Control file
Public WebPath As String 'Path for storing web pictures
Public CoName As String 'Current co name
Public CoCode As String 'Current co code
Public CoColor As String 'Current co color
Public CoFulFill As String 'Current fulfillment status
Public CoDefPrice As String 'Current co default price level
Public varSrchType As Integer 'Type of search to make
Public strCallingForm As String 'Form name making a call to another form
Public strFormType As String 'Type of form to process
Public strReason As String 'Reason for printing form
Public lngCustNo As Long 'Customer number
Public lngEMktID As Long 'Emarket ID number
Public strEMktName As String 'Emarket dealer name
Public EMktPrcLvl As String 'Emarket dealer price level
Public lngOrdNo As Long 'Order number
Public lngInvNo As Long 'Invoice number
Public strInvNo As String 'Invoice number as text
Public lngRANo As Long 'RA number
Public strRANo As String 'RA number as string
Public lngPONo As Long 'Purchase order number
Public lngSKUNo As Long 'Product SKU number
Public strOrdNo As String 'Order number converted to string
Public CustName As String 'Customer name
Public RetailName As String 'Business name on PT and Inv
Public strZipCode As String 'Zip code to lookup
Public CustState As String 'State
Public CustCity As String 'City
Public strCountry As String 'Country
Public strFornCity As String 'Foreign city/zip
Public strFornZip As String 'Foreign postal code
Public strShCntry As String 'Ship-to country
Public strCntryCode As String 'Country code
Public UserName As String 'user name
Public UserID As String 'User ID
Public UserPermits As String 'User permissions
Public UserOK As Boolean 'User verification indicator
Public ARCoArray(8) As Variant 'Multi-dimensional array
Public ARCoCode() As String 'Array of company codes
Public ARCoName() As String 'Array of company names
Public ARCoColor() As String 'Array of company colors
Public ARCoFulfill() As String 'Array of company fulfillment codes
Public ARCODefPrice() As String 'Array of company default price levels
Public CoCount As Integer 'Number of companies
Public arrBookMark() 'Array of inventory bookmarks
Public arrProduct() 'Array of products ordered
Public dbPath As String 'Database path
Public InqOrUpd As Byte 'Sets the comportament for frmOrdInqUpd
Public TMAction 'Store telemarketer process selected
Public OnlyUnShipped As Byte 'Used in OrderSelect
Public MfgCode As String '4-character mfg code
Public curMSRP As Currency 'Mfg suggested retail
Public curVendCost As Currency 'Vendor cost
Public curActualCost As Currency 'Actual cost
Public strCostFormula As String 'Cost formula
Public boolwork As Boolean 'Yes/no work field
Public boolAction As Boolean 'Process flag
Public UpNextNum As Boolean 'Next number switch
Public arrStrText(20) 'Array of text fields
Public arrCurrency(10) 'Array of currency fields
Public arrInteger(10) 'Array of integer fields
Public arrChkBox(10) 'Array of check boxes
Public DispScope As String 'Backorder scope to display
Public strMfgCode As String 'Manufacturer code
Public strCategory As String 'Category code
Public curShipHand As Currency 'Shipping & handling total
'All inventory price levels
Public curRegPrice As Currency 'Green's regular price level
Public curVolPrice As Currency 'Green's volume price level
Public curL3Price As Currency 'Green's level 3 price
Public curL4Price As Currency 'Fourth level price
Public curL5Price As Currency 'Fifth level price
Public curL0Price As Currency 'Level 0(EM) price
Public curItemCost As Currency 'Item cost
Public curMSRPCost As Currency 'MSRP
Public curMinCost As Currency 'Minimum price
Public PckArray() As Currency
Public Num As Integer
Public LineNo2 As Integer
Public Form As Integer

Public HazCode(4) 'Array of haz mat codes per order
Public bkmWorkBookmark As Variant
Public GlobalEMarket As Integer 'EMarket processing only
Public Xtwips As Integer, Ytwips As Integer
Public Xpixels As Integer, Ypixels As Integer
Public IsHazard As Boolean 'Hazardous material flag
'Variables used in caclulating order figures
Private LineNo As Integer 'Line item to work with
Private LineTotal As Currency 'Total cost for line item
Private intRunTot As Currency 'Total cost of all items ordered
Private intItemTot As Currency 'total cost of items in stock to be shipped
Private intOrderTot As Currency 'Ord total including all fees
Private intBOTotal As Currency 'Total cost of BO items
Public BOStatus As Byte 'Backorder status flag
Private WasSaved As Byte
Private KeyHit As Integer 'Was key hit
----------------
Joe
 

Public ARCoArray(8) As Variant 'Multi-dimensional array
Public arrBookMark() 'Array of inventory bookmarks
Public arrProduct() 'Array of products ordered
Public TMAction 'Store telemarketer process selected
Public arrStrText(20) 'Array of text fields
Public arrCurrency(10) 'Array of currency fields
Public arrInteger(10) 'Array of integer fields
Public arrChkBox(10) 'Array of check boxes

Public HazCode(4) 'Array of haz mat codes per order
Public bkmWorkBookmark As Variant


Yeah, over all you do not use to many but your declarations for the arrays are arrays of variants because you have not declared what type of array they are
 
I know because I pass them around and am not always sure what data type will be stored in them during runtime, so I just leave them as variant, I only like to use them when I have to, and thanks for letting me know that not declaring them as something defaults to variant, since I'm such a new programer and all I didn't know that ;)!! ----------------
Joe
 
Yep, the multiple declarations issue is one that has caught a LOT of programmers out in it's time.
 
There are very very few occasions when I use variants. But when I do, I treasure them....

The right way for the right job.
All arguments for Pro/Con may have legitimate uses for specific tasks at certain times.

And then there's the point of what could be considered as an &quot;Optimization Budget&quot;.

To spend time re-doing a small proceedure, finding the ideal way to write the code, when the actual benefits are basically non-noticable, for the sake of &quot;looking good/right&quot;, may be dangerous to the budget.
There are times when it is alright to say: Heck, I'll just use a variant for this....(Please note: I am not speaking about the basics! If you know a string variable will work, then use a string variable, or whatever..)

MS were anyways the ones who went over board teaching the newbies to use variants and used them in many, many code examples, and then turn around and say, &quot;be carefull with the use of variants&quot;.

Some occasions when I like using a variant as an argument or return value are when dealing with arrays, or a datafield class property that sets or returns any type.

Variants are very handy for both (just pass a NULL back, or use the IsArray function to determine if the array has been dimensioned and filled with data, or as a 2nd optional array, or optional multi-dim array)

Um, I would also like to point out that an overuse of public variables is just as bad......

 
BTW:
What is more costly:
A proceedure level variable or module level variable at the moment the proceedure is being ran.
 
So, many would start saying &quot;declare the type a variable will only accept&quot;. And so do I. Doing so adds a data validation bonus. Meaning, it will raise an error for the user, even without making extra error handling procs. This is very, very handy. There are many cases that a user would pass invalid data types and we're not even aware of such possibility and forgot to put error trapping codes. This is the right time that VB do its job, at least, for the validating part.

Still, Variant has its own conveniences. I have functions that returns arrays and accepts arrays as param. I can only think of Variant for the easy way out. (well, if anyone has other solutions, i'd be glad to hear them)

As mentioned, you can also pass especial types (eg Null, Empty) to Variants. After a query, like from a data table, you can return Empty if the action failed and test for the return value if IsEmpty(). This adds readability to your code.
 

>I can only think of Variant for the easy way out

Well, I for one, do not know how to pass an optional array of a specific type (not variant), an optional 2nd, 3rd, ect., array or an optional multi-dimed array....

Therefore, my only choice is to use a variant. I cannot say that is an easy way out...but the only way out.
 
There are only two times I ever use a variant:
[ol]
[li]When adding functionality to functions that also use variants. In that case it is only to mimic the original parameters and return value.[/li]
[li]When I am building classes for handling binary data. In that case I don't care what data type it is and need to be read for any type. For example, a compression or encryption class. I don't care what type of data is coming in, it is just a stream of binary as far as the process is concerned.[/li]
[/ol] ________________________________________
Nature and Nature's laws lay hid in night
God said &quot;Let Newton be&quot;, and all was light
~Alexander Pope~
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top