VBA Migration
Fully Qualified Enumerations
In VBA enumerations were considered to be global but in .NET they are not. This means that in .NET enumerations must be fully qualified with their full enumeration name.
Selection.Find.Wrap = Word.wdFindWrap.wdFindContinue
Word uses loosely typed enumerations
Excel and other applications create typed enumerations which are easier to resolve.
In VBA enumeration constants could be replaced with their numerical value equivalent. This is not possible in VB.NET. Any numerical constants have to be replaced with the corresponding enumeration name. In VB.NET enumerations are classified as formal types and can therefore no longer be implicitly converted to different data types.
In VBA the only type of enumeration in Integer. In VB.NET because enumerations are actual types you must access them with the fully qualifier name of the enumeration.
No Default Properties
In VBA you could assume the default property.
In .NET you must be explicit
For example in Excel Range("B3") = "some text"
is shorthand for Range("B3").Value = "some text"
For example in Excel sMyVariable = ActiveCell
is shorthand for sMyVariable = ActiveCell.Value
For example in Word Cell(1,1).Range = "some text"
is shorthand for Cell(1,1).Range.Text = "some text"
For example in Word ActiveDocument.Sections(1).Footers(wdHeaderFooterPrimary).Range = ""
is shorthand for ActiveDocument.Sections(1).Footers(wdHeaderFooterPrimary).Range.Text = ""
This cannot be converted into a Range
CType(Application.Selection, Word.Range)
You must refer to the Range of the Selection
CType(Application.Selection.Range, Word.Range)
A new section will not be added.
With Application.ActiveDocument.Sections
.Add(.Last)
End With
You must refer to the Range of the Last section
With Application.ActiveDocument.Sections
.Add(.Last.Range)
End With
A new section will not be added.
objField.Code.ToString.IndexOf
You must refer to the Text of the Code
objField.Code.Text.ToString.IndexOf
Arrays
In VBA you can have Option Base 1
In C# (and VB.Net) this is not supported andall arrays must start at 0
Method Calls with Parentheses
Functions and subroutines require parentheses, but methods don't
Call MsgBox("My Message")
In VBA when you use methods, spaces are required rather than parentheses
MsgBox "My Message"
In C# parentheses are required when passing parameters to a method call
Named Ranges
You cannot use array syntax to access the named ranges
myWbk.Names.Item(rangeName)
// the following will not work
myWbk.Names[rangeName]
Inconsistency - Automatic data type conversion
some data types change automatically, but others do not
The following line is fine is VBA as automatic type conversion happens automatically.
sMyVariable = txtTextBox.Text * txtAnotherTextBox.Text
Although this is not true for all operators. The following line however will generate a compile error ?
sMyVariable = txtTextBox.Text + txtAnotherTextBox.Text
Type conversion in this case will have to be explicit
sMyVariable = Val(txtTextBox.Text) + Val(txtAnotherTextBox.Text)
Inconsistency - Value types without a Set keyword
Some variables have to be initialised with the Set keyword but not all of them.
The following line does not require Set
vVariable = ActiveCell
but other variables do
Set vWsh = ActiveSheet
Range.Value
The value of objRange.Value is Nothing when the cell is empty
Dim objRange As Excel.Range
If objRange.Value Is Nothing Then
'the cell is empty
End If
Before referring to any cell you should call the clsCell.TypeReturn function to check the contents of the cell
If clsCell.TypeReturn(objRange) = "Number" Then
End If
sText = (string)objCell.Value2 'this works when the cell contains text
sText = (string)objCell.Value2.ToString() 'this works when the cell doesn't contain text
what if the cell is empty ??
objRange.Value = arArray
test for different size and make this bullet proof !!
what if cells are formatted as text / values etc
For Each does not work
You must use For Loop instead of For - Each for the following collections:
Workbook.Names Collection
Range.Cells Collection
The following code does not work
Dim objName As Excel.Name
For Each objName In Workbooks.Names
objName = objNames.Item(inamescount)
Next objName
Use must use a For Loop instead
Dim objName As Excel.Name
Dim icount As Integer
For icount = 1 To Workbooks.Names.Count
Next icount
The following code does not work
Dim objCell As Excel.Cell
For Each objCell In Range.Cells
Next objCell
Use must use a For Loop instead
Dim objCell As Excel.Cell
Dim icount As Integer
For icount = 1 To Range.Cells.Count
objcell = CType(objSelection.Item(icellcount), Excel.Range)
Next icount
Application Object
In VBA there is an implicit reference to Application
Referring to the Application object:
In Add-ins - cls1Constants.gApplication.ActiveWorkbook
In document level - Globals.ActiveWorkbook
Globals.ThisAddin.Application ?
Globals.Sheet1.Rows.getItem(12,System.Type.Missing) ?
| VBA | C# |
| Dim objChartObjects As Excel.ChartObjects | Excel.ChartObjects objChartObjects |
| objChartObjects = objWsh.ChartObjects | objChartObjects = (Excel.ChartObjects)objWsh.ChartObjects(System.Type.Missing); |
Workbooks
| VBA | C# |
| Dim objWkbs As Excel.Workbooks | Excel.Workbooks objWkbs; |
| objWbks = Application.Workbooks | objwkbs = (Excel.Workbooks)Globals.Workbooks; |
| Dim objWbk As Excel.Workbook | Excel.Workbook objWbk; |
| objWbk = Application.Workbooks("Book1.xls") | objwkb = Application.Workbooks.get_item("Book1.xls"); |
Worksheets
| VBA | C# |
| Dim objWsh As Excel.Worksheet | Excel.Worksheet objWsh; |
| objWsh = Application.Sheets(1) | objWsh = (Excel.Worksheet)Globals.Application.Sheets(1); |
| objWsh = Application.Sheets("WshName") | objWsh = (Excel.Worksheet)Globals.ThisWorkbook.Worksheets.get_Item("WshName"); |
| objWsh = Sheet1 | objWsh = (Excel.Worksheet)Globals.Sheet1; |
Cells & Ranges
| VBA | C# |
| Dim objRange As Excel.Range | Excel.Range objRange; |
| objRange = objWsh.Range("A1") | objRange = (Excel.Range)objWsh.get_Range("A1",System.Type.Missing); |
| objRange = objWsh.Range("NamedRange") | objRange = (Excel.Range)objWsh.get_Range("NamedRange",System.Type.Missing); |
| objRange = (Excel.Range)objRange.Cells[1,2]; | |
| objRange = Range("A1","D4") | |
| objRange.Offset(1,1) | objRange.get_Offset(1,1) |
| objRange.Resize(2,2) | objRange.get_Resize(2,2) |
| Cells(1,1) | Cells[1,1]; |
| Cells.get_Item(1,1); | |
| For icellno = 1 To objRange.Cells.Count | foreach (Excel.Range objcell in objRange) |
| Next icellno | { |
| } | |
| objCell.Value2.ToString(); | |
| System.Convert.ToInt16(objCell.Value2.ToString()); | |
| 'the following line does not work when the cell is empty ? | |
| semptycell = System.Convert.ToString(objCell.Value2); | |
| 'this line works when the cell contains a text string ?? | |
| semptycell = (string)objCell.Value2 | |
| if (semptycell ! Null) | |
| { | |
| scellvalue = objCell.Value2.ToString(); | |
| } |
Colours
RGB(10,20,30) = Microsoft.VisualBasic.RGB()
Word.wdColor = (Microsoft.Office.Interop.Word.wdColor)Microsoft.VisualBasic.RGB()
Word.wdColor = Ctype(Microsoft.VisualBasic.RGB(), Microsoft.Office.Interop.Word.wdColor)
Numbers
VBA.Abs
ABS - Returns the absolute value of a number.
'VBA Code
Abs(-40)
'C# Equivalent
System.Math.Abs(-40)
VBA.CInt
CINT - Returns a number converted to an integer data type.
'VBA Code
CInt(0.2)
'C# Equivalent
System.Convert.ToInt32(0.2)
VBA.Exp
EXP - Returns the base of natural logarithm raised to a power
'VBA Code
'C# Equivalent
VBA.Hex
HEX - Returns the number converted to a hexadecimal
'VBA Code
Hex(iValue)
'C# Equivalent
iValue.ToString("X")
VBA.Fix
FIX - Returns the integer portion of a number.
'VBA Code
'C# Equivalent
VBA.Int
INT - Returns the number rounded down to the nearest integer.
'VBA Code
Int(0.9) = 0
'C# Equivalent
System.Math.Floor(0.9)
VBA.IsNumeric
ISNUMERIC - Returns the value indicating if an expression contains a number.
'VBA Code
IsNumeric(sCharacter)
C# Equivalent, single character
System.Char.IsNumber(sCharacter.Chars(0)) = True;
C# Equivalent, entire string
int integerValue;
string stringValue = "2030";
bool result = int.TryParse(stringValue, out integerValue);
if (result == true)
{ // this string contains a valid integer
}
VBA.Log
LOG - Returns the natural logarithm of a number
'VBA Code
'C# Equivalent
VBA.Mod
MOD - Returns the remainder after division
'VBA Code
'C# Equivalent
VBA.Round
ROUND - Returns a number rounded to a given number of decimal places.
'VBA Code
Round(0.149,2)
'C# Equivalent
System.Math.Round(0.149,2, MidPointRounding.AwayFromZero)
VBA.Rnd
RND - Returns a random number between 0 and 1
'VBA Code
'C# Equivalent
VBA.Sgn
SGN - Returns the sign of a number.
'VBA Code
Sgn(1)
'C# Equivalent
System.Math.Sign(1)
VBA.Sqr
SQR - Returns the square root of a number.
'VBA Code
Sqr(9)
'C# Equivalent
System.Math.Sqrt(9)
Integer Division
C# truncates, VB.Net rounds
Dim itotal As Integer = 20;
Dim ivalue As Integer = 3
Dim iresult As Integer = itotal / ivalue
int itotal = 20;
int ivalue = 3
int iresult = itotal / ivalue;
VBA.Date
The DATE function returns the current system date.
'VBA Code
VBA.Date
'C# Equivalent
VBA.DateAdd
The DATEADD function returns the date to which a specified time interval has been added.
'VBA Code
VBA.DateAdd
Microsoft.VisualBasic.DateAndTime.DateAdd(Microsoft.VisualBasic.DateInterval.Date, _
Number, _
DateValue)
Microsoft.VisualBasic.DateAndTime.DateAdd(Interval, _
Number, _
DateValue)
'C# Equivalent
VBA.DateDiff
The DATEDIFF function returns the number of time intervals between two specific dates.
'VBA Code
VBA.DateDiff
Microsoft.VisualBasic.DateAndTime.DateDiff(Microsoft.VisualBasic.DateInterval.Date, _
Date1, _
Date2, _
FirstDayOfWeek, _
FirstWeekOfYear)
Microsoft.VisualBasic.DateAndTime.DateDiff(Interval, _
Date1, _
Date2, _
FirstDayOfWeek, _
FirstWeekOfYear)
'C# Equivalent
VBA.DatePart
The DATEPART function returns the specified part of a given date.
This method can now take an enumerated constant as well as a string constant.
'VBA Code
VBA.DatePart
Microsoft.VisualBasic.DateAndTime.DatePart(Microsoft.VisualBasic.DateInterval.Date, _
Date, _
FirstDayOfWeek, _
FirstWeekOfYear)
Microsoft.VisualBasic.DateAndTime.DatePart(Interval, _
Date, _
FirstDayOfWeek, _
FirstWeekOfYear)
'C# Equivalent
VBA.DateSerial
The DATESERIAL function returns the date given a year, month and day.
'VBA Code
VBA.Format(VBA.DateSerial(2010,12,1), "dd-mmm")
'C# Equivalent
new System.DateTime(2010,12,1).ToString("dd-mmm")
VBA.DateValue
The DATEVALUE function returns the date given a string representation of a date.
'VBA Code
VBA.Format(VBA.DateValue(2010,12,1), "dd-mmm")
'C# Equivalent
System.Convert.ToDateTime(2010,12,1).ToString("dd-mmm")
VBA.Day
The DAY function returns the day from a given date.
'VBA Code
VBA.Day
Microsoft.VisualBasic.DateTime.Day
'C# Equivalent
??
VBA.Format
The FORMAT function returns the text string of a number or date in a particular format.
'VBA Code
VBA.Format(VBA.Now(), "hh:mm:ss AMPM") = 10:40:17 AM
VBA.Format("12345,"#,###.00") = 12,345.00
VBA.Format("12345,"0.00") = 12345.00
'C# Equivalent
System.DateTime.Now().ToString("hh:MM:ss tt")
System.Convert.ToInt32("12345").ToString("#,###.00")
System.Convert.ToInt32("12345").ToString("0.00")
VBA.Hour
The HOUR function returns the hour from a given time.
'VBA Code
VBA.Hour
'C# Equivalent
??
VBA.IsDate
The ISDATE function returns the value indicating if an expression is a date.
'VBA Code
If (VBA.IsDate("01/12/2014") = True) Then
'C# Equivalent
System.DateTime temp;
if (System.DateTime.TryParse("01/12/2014", out temp))
VBA.Now
The NOW function returns the current system date and time.
'VBA Code
VBA.Now
'C# Equivalent
System.DateTime.Now
VBA.Minute
The MINUTE function returns the minute from a given time.
'VBA Code
VBA.Minute(VBA.Time)
'C# Equivalent
System.DateTime.Now.Minute.ToString
VBA.Month
The MONTH function returns the month from a given date.
'VBA Code
VBA.Month
'C# Equivalent
??
VBA.MonthName
The MONTHNAME function returns the month as a string.
'VBA Code
VBA.MonthName(3)
Microsoft.VisualBasic.DateAndTime.MonthName(Month, Abbreviate)
'C# Equivalent
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(3)
VBA.Second
The SECOND function returns the second from a given time.
'VBA Code
VBA.Second
'C# Equivalent
VBA.Time
The TIME function returns the current system time.
'VBA Code
VBA.Time
'C# Equivalent
??
VBA.TimeSerial
The TIMESERIAL function returns the time for a specific hour, minute and second.
'VBA Code
VBA.TimeSerial
'C# Equivalent
VBA.TimeValue
The TIMEVALUE function returns the
'VBA Code
VBA.TimeValue
'C# Equivalent
??
VBA.Weekday
The WEEKDAY function returns the
'VBA Code
VBA.Weekday("01/12/2010") = 4
Microsoft.VisualBasic.DateAndTime.WeekdayName("01/12/2014")
'C# Equivalent
System.Convert.ToInt32(System.Convert.ToDateTime("01/12/2014").DayOfWeek).ToString();
VBA.WeekdayName
The WEEKDAYNAME function returns the day of the week as a string.
'VBA Code
VBA.WeekdayName(2) = Tuesday
Microsoft.VisualBasic.DateAndTime.WeekdayName(2)
'C# Equivalent
System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.DayNames(2).ToString();
VBA.Year
The YEAR function returns the year from a given time.
'VBA Code
VBA.Year
'C# Equivalent
System.DateTime.Year
Implicit Date Operations
When working with Dates in Excel it is important to know the differences between VBA and .NET
In VBA you can use dates and times as "real" dates and times
#1/4/2007#
or you can use them as date serial numbers
36282.5
Explicit Date Operations
In .NET you will have to convert these dates explicitly.
There are two different ways of doing these conversions
Dim dbMyDate As Double
dbDate = Now().ToOADate
dbDate = System.DateTime.ToOADate(Now())
It is a similar story for dates that are supplied as strings
You should use the Parse method to convert a string to a date
Dim dbMyDate As Double
dbMyDate = System.DateTime.Parse("01 Jan 2008")
In VBA dates are stored internally as a serial value ( the number of days since Dec 30 1899)
in VBA times are stored as fractions.
In VBA dates are stored as a floating-point number and are represented as Doubles.
In VB.NET dates and times are stored completely differently.
In .NET a date maps to a System.DateTime
Converting VBA Doubles into .NET DateTimes
To convert between a VBA Double data type and a .NET DateTime data type you can use the following:
You should use the DateTime's ToOADate and FromOADate methods.
Dim myDate As DateTime
myDate = Date.FromOaDate(Globals.Sheet1.Range("A1").Value2
Dates and DateTime
Range["A1"].Value = "08/11/04"
This value could be interpreted as any of the following dates depending on the locale of the current thread
● August 11, 2004
● November 8, 2004
● November 4, 2008
The workaround is to never pass dates as literal strings into Excel.
Always construct a date using the System.DateTime object and pass it to Excel using the DateTime.ToOADate method
The ToOADate method converts a DateTime to an OLE Automation date which is the date format used by Excel.
System.DateTime odate = new System.DateTime(2014,4,11);
range1.Value = odate.ToOADate();
Excel calculates the number of days elapsed since 31 December 1899
.NET calculates the number of days elapsed since 1 January 1900
To convert an Excel date in 1900 that is earlier than 1 March 1900 into a DateTime object you must add one day
Excel cannot represent days before 1 January 1900 or (I January 1904) so when converting a DateTime into an Excel date, you have to pass a string rather than a number representing the date.
Strings & Characters
| VBA | C# | VB.Net |
| vbCrLf | \r\n System.Environment.NewLine | Microsoft.VisualBasic.Constants.vbNewline Microsoft.VisualBasic.ControlChars.Newline Microsoft.VisualBasic.Constants.vbCrLf Microsoft.VisualBasic.ControlChars.CrLf |
| vbCr | \r | Microsoft.VisualBasic.Constants.vbCr Microsoft.VisualBasic.ControlChars.Cr |
| vbLf | \n | Microsoft.VisualBasic.Constants.vbLf Microsoft.VisualBasic.ControlChars.Lf |
| vbTab | \t | Microsoft.VisualBasic.Constants.vbTab Microsoft.VisualBasic.ControlChars.Tab |
VBA.Asc
ASC - Returns the ANSI number for the first character in a text string.
'VBA Code
Dim sngValue As Single
sngValue = VBA.Asc("A") '=65
'C# Equivalent
Single sngValue;
char tempCharacter = "A"c;
char[] getCharacters = tempCharacter;
char convertCharacter = System.Text.ASCIIEncoding.ASCII.GetBytes(getCharacters)[0];
sngValue = System.Convert.ToSingle(convertCharacter);
'VBA Code
Dim sngValue As Single
sngValue = VBA.Asc("Asometext") '=65
'C# Equivalent
string tempString = "Asometext";
Single sngValue;
char[] getCharacters = tempString.ToCharArray();
char convertCharacter = (char)System.Text.ASCIIEncoding.ASCII.GetBytes(getCharacters)[0];
sngValue = System.Convert.ToSingle(convertCharacter);
VBA.Chr
CHR - Returns the character with the corresponding ANSI number.
'VBA Code
VBA.Chr(65) = "A"
'C# Equivalent
System.Convert.ToChar(65) = "A"
VBA.InStr
INSTR - Returns the position of a substring within a larger string.
In VBA, Instr() returns 1 when the find item is at the start of the string and is also case sensitive
In VSTO, sText.IndexOf() returns 0 when the find item is at the start of the string and is also case sensitive
'VBA Code
If VBA.Instr(sVariable, "find this") > 0 Then
'C# Equivalent
if sVariable.IndexOf("find this") > -1 { }
'VBA Code
If VBA.Instr(1,sVariable,"find this") > 0 Then
'C# Equivalent
if sVariable.IndexOf("find this",0) > -1 { }
'VBA Code
If VBA.Instr(----) > 0 Then
'C# Equivalent
If (sText.IndexOf(-----) > -1) Then
For more details, please refer to the Strings & Characters > Finding
VBA.InStrRev
INSTRREV - Returns the position of a substring within a larger string, from the end.
'VBA Code
VBA.InstrRev(sVariable, "find this", Len(sVariable) )
'C# Equivalent
sVariable.Reverse.IndexOf("find this", 0) - check this !!!
'VBA Code
Do While VBA.InstrRev(---)
Loop
'C# Equivalent
while sText.IndexOf(---) > -1
{
}
VBA.LCase
LCASE - Returns the text string with all characters converted to lowercase.
'VBA Code
VBA.LCase(sVariable)
VBA.LCase("LOWERCASE")
'C# Equivalent
sVariable.ToLower
String.Copy("LOWERCASE").ToLower()
VBA.Left
LEFT - Returns a number of characters from the left of a string.
'VBA Code = C# Equivalent
VBA.Left(sVariable,4) = sVariable.Substring(0,4)
'VBA Code - First 4 characters
VBA.Left(sVariable,4)
'C# Equivalent
sVariable.Substring(0,4)
'VBA Code - Remove the last character
Dim sText As String = "some text"
VBA.Left(sText, Len(sText) - 1)
'C# Equivalent
sText.Substring(0,sText.Length - 1) = "some tex"
VBA.Len
LEN - Returns the number of characters in a string.
'VBA Code
VBA.Len(sVariable)
'C# Equivalent
sVariable.Length
'VBA Code
VBA.Len("my string")
'C# Equivalent
sVariable = "my string"
sVariable.Length
VBA.Mid
MID - Returns the text string which is a substring of a larger string.
'VBA Code = C# Equivalent
VBA.Mid(sVariable,Len(sVariable),1) = sVariable.Substring(sVariable.Length - 1,1)
VBA.Mid(sVariable,Len(sVariable),1) = sVariable.Substring(sVariable.Length - 1)
VBA.Mid(sVariable,Len(sVariable)) = sVariable.Substring(sVariable.Length - 1)
VBA.Mid(sVariable,Len(sVariable),1) = sVariable.Substring(sVariable.Length - 1,1)
VBA.Mid(sVariable,Len(sVariable) - 1,1) = sVariable.Substring(sVariable.Length - 2,1)
VBA.Mid(sVariable,Len(sVariable) - 2,1) = sVariable.Substring(sVariable.Length - 3,1)
'VBA Code - return the first character
VBA.Mid(sVariable,1,1)
'C# Equivalent
sVariable.Substring(0,1)
'VBA Code - return the second character
VBA.Mid(sVariable,2,1)
'C# Equivalent
sVariable.Substring(1,1)
VBA.Right
RIGHT - Returns the number of characters from the right of a text string.
'VBA Code = C# Equivalent
VBA.Right(sVariable,1) = sVariable.Substring(sVariable.Length - 1)
VBA.Right(sVariable,2) = sVariable.Substring(sVariable.Length - 2)
VBA.Right(sVariable,Len(sVariable),1) = sVariable.Substring(sVariable.Length - 1,1)
VBA.Right(sVariable,Len(sVariable),1) = sVariable.Substring(sVariable.Length - 1)
VBA.Right(sVariable,Len(sVariable) - 1) = sVariable.Substring(sVariable.Length - 2)
VBA.Right(sVariable,Len(sVariable) - 5) = sVariable.Substring(sVariable.Length - 6)
'VBA Code - Check the last 4 characters
If (VBA.Right(sVariable,4) = "Text") Then
'C# Equivalent
if (sVariable.EndsWith("Text") = True)
'VBA Code - Return the last character
Dim sText As String = "some text"
VBA.Right(sText,1)
'C# Equivalent
sText.Substring(sText.Length - 1) = "t"
VBA.Space
SPACE - Returns the specified number of spaces.
'VBA Code
Select Case sCountry & Space(20 - Len(sCountry))
Case "England " : Call Something
Case "Germany " : Call Something
Case "France " : Call Something
End Select
'C# Equivalent
switch (sCountry.PadRight(20))
{
case "England " : Call Something
case "Germany " : Call Something
case "France " : Call Something
}
'VBA Code
sValue = Space(5) & "name"
'C# Equivalent
sValue = String.Empty.PadLeft(5) + "name"
VBA.Split
SPLIT - Returns the array containing a specified number of substrings.
'VBA Code
Dim sStringConCat As String
Dim sValues As Variant
sStringConcat = "one,two,three,four"
sValues = VBA.Split(sStringConCat, ",")
'C# Equivalent
string sStringConCat;
string[] sValues;
sStringConcat = "one,two,three,four";
sValues = sStringConcat.Split(",");
sValues = sStringConcat.Split(sDeimiter.ToCharArray());
VBA.Replace
REPLACE - Returns the text string with a number of characters replaced
'VBA Code
Dim sValue As String
sValue = "this is the old text"
VBA.Replace(sValue,"old text","new text") = "this is the new text"
'C# Equivalent
string sValue
sValue = "this is the old text";
sValue.Replace("old text","new text") = this is the new text"
VBA.UCase
UCASE - Returns the text string with all the characters converted to uppercase.
'VBA Code
VBA.UCase(sVariable)
'C# Equivalent
sVariable.ToUpper();
VBA.Val
VAL - Returns the numbers contained in a string as a numeric value of the appropriate data type.
'VBA Code
VBA.Val(sVariable)
'C# Equivalent
System.Int32.TryParse(sVariable, out iValue);
No Fixed Length Strings
In VBA if you assign text that is longer than a fixed length string it is just truncated (?)
IN VB.Net fixed length strings are not supported.
Functions for Bytes / Double Bytes
All the string functions for handling bytes and double bytes in VBA have been removed in VB.NET
In VB.Net all strings are unicode, so converting strings to double-byte character sets is no longer necessary.
| C# | VB.NET |
| sString1 + sString2 | sString1 & sString2 |
| (plus) | (ampersand) |
| While (String.IsNullOrEmpty(sMyString) == false) | While (Len(sMyString) > 0 |
| what is string is null | |
| sText = "some text\r\n" | sText = "some text" |
| \r\n (escape sequence) | vbCrLf |
| \r (escape sequence) | vbCr |
| \n (escape sequence) | vbLf |
| vbNewLine | |
| vbNullString | |
| \t (escape sequence) | vbTab |
| \\ (escape sequence) | vbBack |
| vbFormFeed | |
| vbVerticalTab | |
| @"""" | """" |
| "'\"" |
Files & Directories
In VB.Net you can read and write from a text stream using the StreamReader or StreamWriter objects.
There are also BinaryReader and BinaryWriter objects for binary data.
The StreamReader and StreamWriter objects work either with a filename string or a FileStream object.
The FileStream class provides random access to a disk file and allows you to specify whether you want to create or open a file.
Scripting.Dictionary
The closest equivalent to this in .NET is a System.Collections.Serialized.StringDictionary ??
Keys.CopyTo ??
Windows Forms
VBA Forms cannot be copied or imported into Visual Studio
Forms in VBA are based on the MSForms type library.
Forms in VBA have been replaced with Windows Forms
In most cases Userforms will need to be recreated as Windows Forms.
Instance vs Actual Object
In .NET forms are treated as classes and there is no ambiguity between instances and the actual class itself.
In VBA the correct way to display a userform is to first create an instance and then refer to that instance.
Dim myUserform As New Userform1
Load myUserform
myUserform.Show
However in VBA it is possible to have the following line
Load Userform1
Userform1.Show
In this case the default instance would be used.
Here there is a mix up between the userform object (or instance) and the actual class itself
In .NET we have a New constructor method and a Dispose method for any cleanup
VBA userform - Form_Unload ??
Application.DoEvents
System.Windows.Forms.Application.DoEvents
Modal vs Modeless
VBA userforms are modal by default.
In .NET windows forms are modeless by default
This is the preferred method
Dim myUserform As New Userform1
Userform1.Show
The following would also work but not as common
Dim myUserform As Userform1 = New Userform1
Userform1.Show
Show vs ShowDialog
.Show - displays a modeless form
.ShowDialog - displays a modal form
Userform_Terminate
Events
VBA userforms have 23 different events
Windows Forms have 83 different events
Validating event associated with all controls ?
"LostFocus" ??
ToolTips
In the section "Common Controls" there is Tooltip control.
There is no ToolTipText property associated with any of the controls.
Drag this control to your form and it will show up below the form.
This control can then be used to associated a tooltip with another control.
Keystrokes
It is possible to monitor the user's keystrokes while working in a windows form.
Set the Form's Keypreview property to True
Form_KeyUp
Form_KeyDown
Form_Keypress
Different Controls
Several controls have had their names changes and also some properties and methods have changed.
| VBA | .NET |
| CommandButton | Button |
| Frame | GroupBox |
| Image | PictureBox |
| ListBox | cannot habe multiple columns |
| MultiPage | TabControl |
| Optionbutton | RadioButton |
| ScrollBar | HScrollBar or VScrollBar |
| SpinButton | NumericUpDown or DomainUpDown |
| TabStrip | TabControl |
| ToggleButton | CheckBox (with appearance = Button) |
Different Properties
| VBA | .NET |
| TextBox.Alignment | TextBox.TextAlign |
| TextBox.Locked | TextBox.ReadOnly |
| TextBox.Change | TextBox.TextChanged |
| CommanButton.Move | Button.SetBounds |
| CommanButton.SetFocus | Button.Focus |
| CommanButton.Validate | Button.Validating |
| TextBox.SelLength | TextBox.SelectionLength |
| TextBox.SetStart | TextBox.SelectionStart |
| TextBox.SelText | TextBox.SelectionText |
| Label.Alignment | Label.TextAlign |
| Label.BackStyle | Label.BackColor (set as transparent) |
| Label.Caption | Label.Text |
| Label.WordWrap | (automatic) |
| ComboBox.List | ComboBox.Items |
| ComboBox.ListCount | ComboBox.Count |
| ComboBox.ListIndex | ComboBox.SelectedIndex |
| ComboBox.Locked | ComboBox.DropDownStyle = DropDownList |
| ComboBox.Style | ComboBox.DropDownStyle |
| ComboBox.AddItem | ComboBox.Items.Add (or AddRange or Insert) |
| ComboBox.RemoveItem | ComboBox.Items.Remove |
| ComboBox.Change | ComboBox.TextChanged |
| ComboBox.Click | ComboBox.SelectedIndexChanged |
| ListBox.Column | ListBox.ColumnWidth (or MultiColumn) |
| ListBox.List | ListBox.Items |
| ListBox.ListColumn | ListBox.Count |
| ListBox.Listindex | ListBox.SelectedIndex |
| ListBox.MultiSelect | ListBox.SelectionMode |
| ListBox.SelCount | ListBox.Count |
| ListBox.Selected | ListBox.GetSelected (or SetSelected) |
| ListBox.AddItem | ListBox.Items.Add (or AddRange or Insert) |
| ListBox.RemoveItem | ListBox.Items.Remove |
| ListBox.ItemCheck | n/a |
| CheckBox.Alignment | CheckBox.CheckAlign |
| CheckBox.Style | CheckBox.Appearance |
| CheckBox.Value | CheckBox.CheckState |
| CheckBox.Click | CheckBox.CheckStateChanged |
| OptionButton.Alignment | OptionButton.TextAlign |
| OptionButton.Appearance | OptionButton.FlatStyle |
| OptionButton.Value | OptionButton.Checked |
| OptionButton.Click | OptionButton.CheckedChanged |
Controls that cannot be added to VSTO Excel workbooks or VSTO Word documents
A number of windows form controls cannot be added to your workbook or document
| Group Box | This control cannot be added at design time because the group box requires the container to support drag and drop functionality which the Excel workbooks and Word documents do not. There are two workarounds (1) Add a group box programmatically at run-time or (2) create a custom user control to contain the group box and the controls inside it. This control can then be added at design-time. |
| Binding Navigator | This control doesn't work with the VSTO control hosting architecture. This control relies on a container model that is not supported by VSTO. |
| MenuStrip | This control can only be added to a windows form |
| RichTextBox | This control contains several bugs when added at design-time. It can be added at run-time though ?? |
Locale / Culture
Visual Studio 2008 and Earlier
When programming against Excel using managed code you could get certain methods and properties behaving differently depending on the locale of the current thread.
This problem only occurs in COM Add-ins, Automation add-ins and Automation executables.
This problem did not occur in document level solutions or add-ins built using VSTO.
If you want to define a formula for a Range and you are in the french locale you must use localised french formula names.
Range["A1"].Formula = "SOMME(3;4)";
Excel expects localized strings for date formats, number formats and formula names.
You could get around this issue by accessing these properties using reflection.
Reflection enables you to specify an English locale and write code that will work regardless.
Excel.Range range1 = sheet.Range["A1"];
typeof(Excel.Range).InvokeMember("Formula",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.SetProperty,
null, range1,
new object[]{"=SUM(10,20)"},
System.Globalization.CultureInfo.GetCultureInfo(1033));
VSTO Solutions
VSTO solutions solve this locale problem by using a transparent proxy that sits between Excel and VSTO.
This proxy forces a US English locale which matches the behaviour in VBA.
A new attribute was added to the AssemblyInfo.cs file to resolve this issue.
The default value for this attribute is true.
This transparent proxy can:
● slow the code slightly
● cause objects to look slightly different in the debugger
This proxy was removed in .NET 4.0
You can bypass this proxy by setting the assenbly level attribute ExcelLocale1033 to false in AssemblyInfo.cs
[assembly: ExcelLocale1033(false)]
Or alternatively if you only want to bypass for a particular method you can use:
Microsoft.Office.Tools.Excel.ExcelLocale1033Proxy.UnWrap method
This method returns the raw PIA object which exposes you to the locale issue.
Handle Culture Issues
CultureInfo baseCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo(xlapp.LanguageSettings.LanguageID(Office.MsoAppLanguageID.msoLanguageIDUI));
// do something
System.Threading.Thread.CurrentThread.CurrentCulture = baseCulture;
© 2026 Better Solutions Limited. All Rights Reserved. © 2026 Better Solutions Limited TopPrevNext