VB.Net Initialization inside loop [closed] - vb.net

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
code1
while
dim number as integer = 0
'some code here
end while
code2
dim number as integer
while
number = 0
'some code here
end while
What is the difference in code 1 and code 2 in terms of speed?
What else is their difference?
What is the best practice to use? thank you

In code 1, your variable's scope is constrained to the while-block.
In code 2, your variable's scope goes beyond the while-block. For example if you define your while block within a function, the scope of the variable is the whole function.
You can note the difference if you have the same variable within multiple blocks:
while
dim number as integer = 0
x = number // x is 0
number = 1
end while
while
dim number as integer = 0
x = number // x is 0
end while
This code is fine, where as the following
dim number as integer = 0
while
x = number // x is 0
number = 1
end while
while
x = number // x is 1
end while
Both ways are fine. Speaking of performance - do not care, if you need to improve the performance of your code you will most likely need to touch a different place. Things like this are therefore often called "micro-optimizations".
Speaking of practice, it is usually best to define the variable as close to its use as possible. So if you only need the variable (and its state) within your while-loop, define it there. If you need to read the value after the while-loop, define it outside. If you use a tool like ReSharper it will even suggest to move your definition to the inner scope (here the while loop) if you place it outside and do not use it afterwards.

There should be no difference in speed of the 2 approaches. the compiler will optimize this for you. You can check the resultant IL code using Ildasm.exe.
The "best practice" is to use the smallest possible scope, i.e. code 2.

You shouldn't care about speed difference between these two. It will be extremely small (if any!).
Other differences? Second code makes number accessible after while loop, which may or may not what you want.
General rule: keep variables at the smallest possible scope, which means if you only need the variable within loop, declare it within loop. If you need it's value to be accessible when loop ends, declare it before loop.

Related

VBA - What is the purpose of the `With` statement [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I read the With-Statement documentation from Microsoft and still don't understand what the purpose of the With statement is...
Xpost from Reddit, thought this should really be somewhere on Stack Overflow and couldn't find any questions of this nature.
Introduction to With
Imagine the following code (Example A):
ThisWorkbook.Sheets(1).Range("A1").Font.Color = rgb(255,0,0)
ThisWorkbook.Sheets(1).Range("A1").Font.Bold = true
ThisWorkbook.Sheets(1).Range("A1").Font.Italic = true
ThisWorkbook.Sheets(1).Range("A1").Font.Size = 16
If we count the .s, in this example there are 13. This means that objects are accessed via a property accessor, 13 times in our code.
What happens when we use a With statement instead? (Example B):
With ThisWorkbook.Sheets(1).Range("A1").Font
.Color = rgb(255,0,0)
.Bold = true
.Italic = true
.Size = 16
End With
If we count the .s in the new code, we see property accessors are only called 7 times! So we just halfed the amount of work that VBA had to do by using a With statement!
This is the primary benefit of using the With statement.
How it works internally
Internally VBA is doing something like this (Example C):
Dim temp1 as Object
set temp1 = ThisWorkbook.Sheets(1).Range("A1").Font
temp1.Color = rgb(255,0,0)
temp1.Bold = true
temp1.Italic = true
temp1.Size = 16
set temp1 = nothing 'More specifically temp1 now calls IUnknown::release()
So you can actually imitate the behaviour of With with this code, but With uses "hidden variables" which don't pollute your local variable scope, so this may be preferred.
Performance Caveats
In regards to performance, the With statement can be used in such a way that it has a performance detriment instead of a performance benefit.
1. A is a local variable
Dim A as SomeObject
set A = new SomeObject
With A
.B = 1
.C = 2
.D = 3
End With
In this case A is a local variable. If we run through our conversion:
Dim A as SomeObject
set A = new SomeObject
Dim temp1 as SomeObject 'Unnecessary call
set temp1 = A 'Unnecessary call
temp1.B = 1
temp1.C = 2
temp1.D = 3
set temp1 = nothing
We see there is potentially some performance detriment in our code, because temp1 needs to be defined and set. The performance decrease will be relatively negligible compared to the property accessors though, so it's unlikely to be noticable. Note that the performance decrease is largely negligible because setting an object doesn't transfer the whole object, but transfer a pointer to the object, which is extremely performant.
PS: This performance degradation is just hypothetical at the moment, I'll confirm whether this is true or whether the performance is optimised away by the compiler.
2. A is a MEMBER variable
If we have a class with the following code:
Public A as object
Sub Test
With A
.B = 1
.C = 2
.D = 3
End With
End Sub
In this case A is a member/property variable. So actually some information is hidden. Let's correct that:
Public A as object
Sub Test
With Me.A
.B = 1
.C = 2
.D = 3
End With
End Sub
Ah, now we can see that by using With we are essentially saving 3 member accessor calls:
Dim Temp1 as object
set Temp1 = Me.A
Temp1.B = 1
Temp1.C = 2
Temp1.D = 3
set temp1 = nothing
vs
Me.A.B = 1
Me.A.C = 2
Me.A.D = 3
Ultimately what I'm saying is VBA may be using hidden variables that you can't see and thus what's really going on under the hood is very context specific. What you are doing may warrant the usage of With in some cases and others not. If in doubt, use With because the performance benefits of getting it wrong far outweigh the performance detriments otherwise.
Note: There are a few small benefits to the With statement regarding speed of writing code and representation of hierarchy, however these are mainly my personal opinion and do not belong here.
P-Code and Performance Measurements
In case interested, here are some dumps of the PCode for a set of examples with and without the With Statement
Of course the P-Code is only half the story as different P-Code operations will each have different speeds. Here's a comparison.
The first 3 columns display a test with the 3 cases described at the beginning of this post. The rest of the tests are relatively random but here's what I learnt:
Local Variables in a with statement appear to be much faster than accessing Member variables.
Using with has performance penalties for small number of calls.
As expected With A.O.O performs signficantly better than A.O.O.Prop=...
With actually has noticable speed difference. Therefore if you can try to keep your With statements outside of any loops you have!
Note: all tests ran on Mac version of VBA in Excel 2011
Note: All tests run over 10^8 iterations - this means these performance differences, although there, are tiny!!

Check how many times a character occurs in a word (VB) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have an array that contains characters converted from a word via .ToCharArray method. I would like to check how many times a letter occurred in this array (word). How can I do this?
One way is a lookup:
Dim letterLookup = yourCharArray.ToLookup(Function(c) c)
' For example the letter e, note that it's case sensitive '
Dim eLetterCount As Int32 = letterLookup("e"c).Count()
This is efficient and has the advantage that you can even check letters which aren't contained in the String/Char(), you will get 0 as result.
By the way, you don't need to use ToCharArray, you could use this code on with original string.
If you wanted to list all contained letters:
Dim allLetters As IEnumerable(Of Char) = letterLookup.Select(Function(kv) kv.key)
If you wanted to ignore the case, so treat e and E as equal:
Dim letterLookup = yourCharArray.tolookup(Function(c) c, StringComparer.CurrentCultureIgnoreCase)
For example the word 'tent'. The program would check which letter
occurs more than once (t) and find the position in the array (in this
case 0,3). It will also find the position in the array of the other
letters.
Then i would use a different approach also using LINQ:
Dim duplicateLetterPositions As Dictionary(Of Char,List(Of Integer)) = yourCharArray.
Select(Function(c, index) New With {.Char = c, .Index = index}).
GroupBy(Function(c) c.Char).
Where(Function(grp) grp.Count > 1).
ToDictionary(Function(grp) grp.Key, Function(grp) grp.Select(Function(x) x.Index).ToList())

Have one variable have multiple values in different methods [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Trying to create a universal placeholder for all methods in my class instead of having to declare multiple varibles per class, else declaring multiple instances of a class and using its methods can be quite costly
dim beginIndex, endIndex as integer
public sub GetLastFiveLetters(str as string)
' assume string is 10 characters long
beginIndex = 5
endIndex = 10
ResetVariable() 'I want beginIndex and endIndex to be 5 and 10 after I call this method
return = str.substring(5, 10)
end sub
public sub GetFirstFiveLetters(str as string)
'assume string is 10 characters long
beginIndex = 0
endIndex = 5
ResetVariable() 'I want beginIndex and endIndex to be 0 and 5 after I call this method
return = str.substring(0, 5)
end sub
public sub ResetVariables()
beginIndex = 0
endIndex = 0
end sub
The reset variable method is simply there for example purposes, what i want to do is be able to use a variable with multiple values across multiple methods...
So when i call reset variable, even though im technically reseting the variable across all methods, i want to variables to retain their method specific values ... so in the first method even though i called the reset method, i want beginIndex to still be 5 and endIndex to still be 10, it is only in the resetvariable method where beginIndex will be 0 and endIndex will be 0
Regarding storing variables in methods:
... declaring multiple instances of a class and using its methods can be quite costly
WRONG. Variables declared in methods, i.e. local variables, exist only while the method is being executed. On the other hand, variables declared at the class level, i.e. fields, exist for each class instance or object for its the whole life time.
You must make a distinction between the variable declaration and the memory that a variable uses at runtime. The variable declaration itself is not compiled into code. Only the variable accesses (i.e. setting or reading the variable) are. At runtime, local variables start to exist when a method is called and cease to exist after the method returns.
Class fields, however, exist as long as the objects exist, whether a method is being called or not.

VBA code 3 columns to 1, using a specific order [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have a list of data, distributed with a non-homogeneous pattern, on 3 columns. The challenge is to write a vba code "smart enough" to copy and paste all these numbers on one column, putting them in order, one below the other one: 1, 2, 3, 4, 4.1, 4.2 etc.. without missing any of them.
Could someone help me in this task? Because I see a lot of complexity and I have no idea how to manage it. Thank you!
As I understand it, you're looking to order this in a specific way that isn't necessarily how Excel would sort by default. The values look like version numbers or nested task IDs.
Stack Overflow isn't really a "solve your problem for you" kind of place, but I can definitely get you started. Here's what you'll need to do:
Get all the values, preferably into a Collections object. Make sure to omit blank cells.
Convert each value into a new format which a) is sortable, and b) can be reverted to the original format. For example, let's say these are version numbers, and any given number can be as high as 999, and there can be up to 4 items (e.g. 123.10.15.9 is valid, as is 9.5). Convert these to the form 000000000000 (that's 12 0s). You can do this by using Split() to divide the values using the "." delimiter, then padding the value out. This might look something like this:
.
'Converts 1 => 001000000000
' 1.1 => 001001000000
' 2.4.7 => 002004007000
' 65.339.1 => 065339001000
Function ConvertToSortableVersionNumber(value As String) As String
'Add all the parts of the value (. delimited) to a collection
Dim vnPart As Variant
Dim error As Boolean: error = False
Dim Parts As Collection
Set Parts = New Collection
For Each vnPart In Split(value, ".")
'Make sure this can actually be formatted as needed.
If Len(vnPart) > 3 Then
error = True
Exit For
End If
'Add this part to the Parts collection
Parts.Add vnPart
Next vnPart
'Now make sure there are 4 parts total
If Parts.Count > 4 Then error = True
'Check for errors
If error Then
'There is an error. Handle it somehow
End If
'If there are less than 4 items in the collection , add some
While Parts.Count < 4
Parts.Add ("000")
Wend
'Now, assemble the return value
Dim retVal As String
Dim item As Variant
For Each item In Parts
retVal = retVal & Right(String(3, "0") & item, 3)
Next item
'All set!
ConvertToSortableVersionNumber = retVal
End Function
Sort the collection (this page has a good example of sorting a collection in memory).
Create an array with new values converting back to the original format (much easier since the inputs will be highly standardized).
Write the array to a new range--and you're done!
Take a stab at it. I think you'll find that Stack Overflow is much more helpful once you can show the work you've already done, what you've tried, and what specifically is giving you trouble.
Good luck!
If you have 2010 or later the following formula will do it:
=IFERROR(SUBSTITUTE(SUBSTITUTE(AGGREGATE(15,6,--SUBSTITUTE($A$1:$C$10,".","000")*--(1 & REPT("0",9-LEN(SUBSTITUTE($A$1:$C$10,".","000")))),ROW(1:1)),"0000",""),"000","."),"")
If you have 2007 or earlier than it will need to be an array formula:
=IFERROR(SUBSTITUTE(SUBSTITUTE(SMALL(IF($A$1:$C$10<>"",--SUBSTITUTE($A$1:$C$10,".","000")*--(1 & REPT("0",9-LEN(SUBSTITUTE($A$1:$C$10,".","000"))))),ROW(1:1)),"0000",""),"000","."),"")
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when leaving edit mode.
Column E is the first formula and Column F is the second.

Is it good practice to assign a value of FALSE to a function at the beginning and then TRUE only when it reaches the end? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
For the functions I have, I have many scenarios where, based on IF checks, I have
MyFunction = False
Exit Function
When it reaches the end of the function, then and only then does the MyFunction = True occur. Because of the repetition of the False assignment, I was wondering if it is good practice to instead initially set MyFunction = False for example after the Dim of variables, and then only have it become true when everything goes through properly. Is there any reason this would either increase robustness or decrease it?
Every type of variable has an 'empty' value (after Dim without setting it to something). Boolean values are always false... numerical values are 0, strings are "" and variant / objects are empty... setting it to something it already is, only can slow down.
Knowing that its not neccessary to set a bool to false after dim... (or a numerical value to 0)
EDIT:
This also counts for functions even if there is something like Function MyFunction(Optional a as Boolean = True) as Boolean a will be False at the start then it checks if there is something to set to and if not it will be set to true.... also the function itself will be false at the start. It is differnt when doing something in C or other scripting languages, but VBA is set to change all bits inside a reserved range for a value to 0.