In some tutorials I find variables used with ampersand at the end of their names like with boxType& here:
%Include "lsconst.lss"
Dim boxType As Long, answer As Integer
boxType& = MB_YESNO + MB_ICONQUESTION
answer% = MessageBox("Do you want to continue?", boxType&, _
"Continue?")
I am learning Lotus Script while developing, so I seem to have missed some basics!
I would like to know what this ampersand in this context mean.
This a a so called "type suffix" and tells you, that boxType is of Type Long and answer is of type Integer. Usually you use this instead of declaring variables explicitly. Or you use it, to "see" in the variable, what type it is. Read this link or your designer Help (Topic: About data types (LotusScript Language) ) to find out more about this.
Here are the prefixes from the linked document:
Integer = %
Long = &
Single = !
Double = #
Currency = #
String = $
Related
Okay I have never used vb script and I am trying to convert a legacy vb module to c#. The syntax is fine but man this function definition just complete threw me for a loop.
What does $ % and # mean in the declaration.
Like for example pop(name$,balance#, id%)
They are called Type Characters. From MSDN:
Visual Basic supplies a set of identifier type characters, which you can use in a declaration to specify the data type of a variable or constant.
Here is the list, reprinted from the link:
Identifier type character Data type Example
---------------------------------------------------------------------
% Integer Dim L%
& Long Dim M&
# Decimal Const W# = 37.5
! Single Dim Q!
# Double Dim X#
$ String Dim V$ = "Secret"
I'm writing a mid-size script in vba with ~40 subs and one of my subs contains >60 variables now which makes it somewhat hard to keep track of all declared variables. (Do I have a variable for this or that already? Should I maybe recycle variables for multi-purpose, did I declare variables that are no longer used, etc.)
Right now the declarations are sorted historically which means when I declared a new variable I put the line below all other declarations, but that does not seem like good coding practice.
Factors that come into my mind are by data type (used types are Boolean, Long, Single, Double, String, Range, Object and Variant including arrays of different data types. These again I could sort by size, alphabetically, purpose, etc.), alphabetically, historically (which I don't like anymore), by 1st appearance in the sub (which would need most maintenance work), by purpose (i.e. group the variables i, j and k together) and grouped by in which parts of the sub they will be used. (lower half, middle, bottom, etc.)
So I wonder as a reader of my code which order you would like most and to what degree I should consider grouping the variables by their appearance in the sub.
Are there any standardized good practices for order of variable declaration?
Maybe some examples to study?
Greetings, andy01q
PS: Note that I would usually go like "Dim a, b, c as Long" in other languages, but since vba turns out to declare a and b as variant with that line of code I decided to give each variable its own line (to avoid errors in which I accidentally declared variables as Variant between other variables that all have the same type.) which avoided errors but resulted in the given mess.
In some ways it doesn't matter what you do as long as it is reasonable and you do it consistently. This is one of the things which I gleaned from book "Code Complete" by Steve McConnell. This book contains excellent suggestions about things like variable naming, code layout, comment style, etc. My VBA became much more polished after reading that book (which mostly uses C and Pascal for examples but is easily applied to just about any languages).
I wrote a sub to expand Dim lines:
Sub expand(dimLine As String)
Dim fragments As Variant
Dim i As Long, n As Long, myType As String
Dim last As Variant
Dim expanded As String
fragments = Split(dimLine, ",")
n = UBound(fragments)
last = Split(Trim(fragments(n)))
myType = last(UBound(last))
For i = 0 To n - 1 'excludes last fragment
expanded = expanded & IIf(i = 0, "", ",") & fragments(i) & " As " & myType
Next i
expanded = expanded & IIf(n > 0, ",", "") & fragments(n)
Debug.Print expanded
End Sub
If you type expand "Dim a, b, c as Long" in the Immediate Window it expands to
Dim a As Long, b As Long, c as Long
which can be pasted directly into your code. Having written this, I never found it particularly useful -- but then again I've never had a sub with >60 variables. Maybe it could help you.
On Edit: expand can be modified to copy to the clipboard instead of (or in addition to) printing to the immediate window. To do so:
1) Add a reference to Microsoft Forms 2.0 Object Library to your project
2) Include the declaration Dim clip As New DataObject
3) Replace (or supplement) the line Debug.Print expanded by the two lines
clip.SetText expanded
clip.PutInClipboard
Then the expanded declaration is ready to paste into the code.
I'm experimenting with learning how conversions work between variable types. Right now, I'm looking at using one conversion inside a Try/Catch (for values that can't convert). Is there a way to have a string representation of a value (obtained from a TextBox), convert it to a test type, and then see how that converts to all the other VB standard types in a loop? Or even better if there is a resource that already does this.
I can do this, but the code is very close to being repetitive and I'm hoping for a loop of some kind to simplify and shorten it.
First of all, there is no such thing as variable type in VB.net. May be you confusing with object variables - but this is not the same thing
Dim o As Object
o = 1 ' integer
The type that is stored in o is still integer. It is boxed.
Dim i As Integer = CInt(o)
You just un-boxed it. It works because object is lowest of types and all other derive from it. So, it can "box" any other type.
In UI we use text boxes to collect data. Text boxes can contain only string. And unless you writing these strings to a file like txt or xml you usually need to convert these strings to a type you use in application.
Dim port as Integer = Convert.ToInt32(txtPort.Text)
This is not really the area where you can determine, what type is in that text box. You really need to know upfront - what are you expecting there? You can test your text for being one type or another by using
Integer.TryParse
Date.TryParse
.....TryParse
.............
But the thing is, some data can successfully pass this test fro multiple types.
Good question. While it is possible to declare variables of type type and use them in a loop, these cannot be used in declarations or DirectCast.
Dim types() As Type = {GetType(Integer), GetType(Double)}
Dim testType As Type = GetType(Double)
The easiest way might be to test each value individually something like this (although you'll probably want a try-catch for each or all the items).
Dim xInteger As Integer
xInteger = TextBox1.Text
s &= "Integer: " & xInteger.ToString & vbcrlf ' or some test
Dim xDouble As Double
xDouble = TextBox1.Text
s &= "Double" & ": " & xDouble.ToString & vbcrlf
...
I'm just looking at some VB.NET code and I came across this:
Dim var%
Later var is set to 0.
What's the purpose of the percent sign (%)?
(Google and SO search failed me)
Dim varname% is ancient BASIC syntax for "varname is an integer". This has been around for a very long time in the history of the BASIC family, and is supported in Visual Basic.NET (although I, personally, wouldn't recommend it - it can be rather opaque, as discovered by you).
It is shorthand for declaring "var" as of Type Integer, and has roots in the early, early days of BASIC (yes...old-school DOS BASIC).
So this:
Dim var%
is equivalent to:
Dim var As Integer
Here is the actual MS documentation:
https://support.microsoft.com/en-us/kb/191713
% Integer
& Long
! Single
# Double
$ String
# Currency
Putting a % sign at the end of the variable name in Visual Basic indicates that it is an integer. This was used by programmers in the old VB days, I am not sure why it is still present in VB.NET. Don't use it in new code, for all you know it might be gone in future versions of VB.NET.
& : Long
% : Integer
'# : Double
! : Single
# : Decimal
$ : String
I'm trying to get all property names / values from an Outlook item. I have custom properties in addition to the default outlook item properties. I'm using redemption to get around the Outlook warnings but I'm having some problems with the GetNamesFromIDs method on a Redemption.RDOMail Item....
I'm using my redemption session to get the message and trying to use the message to get the names of all the properties.
Dim rMessage as Redemption.RDOMail = _RDOSession.GetMessageFromID(EntryID, getPublicStoreID())
Dim propertyList As Redemption.PropList = someMessage.GetPropList(Nothing)
For i As Integer = 1 To propertyList.Count + 1
Console.WriteLine(propertyList(i).ToString())
Console.WriteLine(someMessage.GetNamesFromIDs(________, propertyList(i)))
Next
I'm not totally sure what to pass in as the first parameter to getNamesFromIDs. The definition of GetNamesFromIDs is as follows:
GetNamesFromIDs(MAPIProp as Object, PropTag as Integer) As Redemption.NamedProperty
I'm not totally sure what should be passed in as the MAPIProp object. I don't see this property referenced in the documentation. http://www.dimastr.com/redemption/rdo/MAPIProp.htm#properties
Any help or insight would be greatly appreciated.
I think I figured it out. I have used VBA only, so you need to "think around" it's limitations, it will follow the same scheme in VB.NET.
The function signature is this:
Function GetNamesFromIDs(MAPIProp As Unknown, PropTag As Long) As NamedProperty
As the first parameter it requires an object which supports the IUnknown interface. Looking at the Redemption docs it became clear that there is an interface named _MAPIProp, from which many other RDO objects are derived (IRDOMail is among them). So this must be the very RDOMail you are trying to get data out of.
Knowing that, it needed only one other subtle hint from the docs to get it working:
Given a prop tag (>= 0x80000000),
returns the GUID and id of the named
property.
So property tag must be >= 0x80000000, this means it wont work for all properties, but just for the custom ones (I guess that is the distinction in this case, correct me if I'm wrong.) Passing in property tags not fulfilling this condition raises an error message (0x8000ffff "unexpected results").
Here is my code. It is VBA, so forgive me the Hex() blunder, as VBAs long integer overflows for numbers that big. I am sure you will get the picture.
Sub GetNamesFromIds()
Dim rSession As New Redemption.RDOSession
Dim rMessage As Redemption.RDOMail
Dim PropertyList As Redemption.PropList
Dim PropTag As Long
Dim EntryId As String
Dim i As Integer
rSession.MAPIOBJECT = Application.Session.MAPIOBJECT
' retrieve first random mail for this example '
EntryId = ActiveExplorer.CurrentFolder.Items(1).EntryId
Set rMessage = rSession.GetMessageFromID(EntryId)
Set PropertyList = rMessage.GetPropList(0)
For i = 1 To PropertyList.Count
PropTag = PropertyList(i)
If "0x" & Right("00000000" & Hex(PropTag), 8) > "0x80000000" Then
Debug.Print
If IsArray(rMessage.Fields(PropTag)) Then
Debug.Print Hex(PropTag), "(Array:", UBound(rMessage.Fields(PropTag)), "items)"
Else
Debug.Print Hex(PropTag), "(", rMessage.Fields(PropTag), ")"
End If
Debug.Print " GUID:", rMessage.GetNamesFromIds(rMessage, PropTag).GUID
Debug.Print " ID:", rMessage.GetNamesFromIds(rMessage, PropTag).ID
End If
Next
End Sub
First snippet from the output:
8041001E ( urn:content-classes:message )
GUID: {00020386-0000-0000-C000-000000000046}
ID: content-class
Well, for background info, the author suggests using something like OutlookSpy to see how Outlook stores the properties.
Looking at this exchange (make sure to read through all the follow-up responses), there isn't much more (in fact, I think at one point the Outlook MVP types GetNamesFromIDs when he means GetIDsFromNames).
What you might try is using GetIDsFromNames to see what that returns, and then use that to pass to GetNamesFromIDs.
I've used Redemption before, but not in this particular manner, so that's all I've got for you ...