In VBA, When I use Dir function first with a path as argument, then later without any argument, it returns the name of next file in the path. It stores the last used path even after the execution of that function is complete. As far as I know, to 'remember' something in a normal function, we need to use a global variable. How does Dir function remember it. I think I am missing some concept in VBA here.
Static variables are the missing link to the puzzle. Although, there may very well be something else going on, Dir() behaves like it has a static variable that holds the last call to the function. It will hold this information until the execution environment is stopped or reset.
Here is a simple a simple example of a static variable:
Sub Test()
Dim n As Long
For n = 1 To 10
Debug.Print Counter
Next
End Sub
Function Counter()
Static count As Long
count = count + 1
Counter = count
End Function
I ran in a problem with an inadequate type declaration for the counter variable of a for-next loop.
What´s wrong with this code snippet?
For n As Byte = 16 to 2 Step -1
Debug.Print(n)
Next
-> The loop is never entered,
while the code
For n As SByte = 16 to 2 Step -1
Debug.Print(n)
Next
works as expected.
I´ve been using VB since 1994, currently Visual Studio Community 2019, V16.8.2, but never ran into this problem.
If n needs to be of a "signed" datatype when Step is of type SByte, Integer ..., to handle neg. numbers, why do I not get an Error, Alert ... from the VS-Compiler?
There is also not hint within the MS doc.
Sure this "problem" can be avoided by using (signed)Byte, Integer, double or decimal as datatypes, but I´d like to understand why VS doesn´t give any alert.
Did I miss something?
Regards
Werner
My question is how to read beginning from the end of a text file.
For example,
do
read(1,*) i
print *,i
end do
will read each line in the file 1, and print the contents to the terminal. How would I do this starting from the end of the file?
You can achieve what you want by using inquire, access=stream, and the pos tag in the read statement. A quick 10 minute exercise gives the following.
program foo
implicit none
integer fd, i, j, m, n
character, allocatable :: s(:)
character :: c
open(newunit=fd,file='foo.f90',access='stream',status='old', &
position='append')
inquire(fd, pos=n)
allocate(s(n))
m = 1
do i = n-1, 1, -1
read(fd, pos=i) c
s(m:m) = c
if (iachar(c) == 10) then
do j = m, 1, -1
write(*,'(A1)',advance='no') s(j)
end do
m = 1
else
m = m + 1
end if
end do
write(*,*)
do j = m-1, 1, -1
write(*,'(A1)',advance='no') s(j)
end do
write(*,*)
close(fd)
end program foo
Save this into a file named foo.f90, compile, and run. Someone here can make it more elegant. Edited original version: don't need to use array sections for s(j).
It is not possible. Reading always starts from a certain point, and proceeds forward. By default it starts from the first byte; but you can jump to some other location.
The critical issue is, in a free-format file, there is no way to know where the lines start unless you read the file. You could jump to the last byte, check whether it is a line separator or not, then jump to the byte before it if it wasn't, crawling back till you find a newline, but it would be very inefficient.
A better way would be to read the whole file once, remembering where the newlines were; then iterate this array backwards, jumping to each line's start position to read it. This is not as inefficient, but it is not great, either.
The best way, if you have the memory for it, is to read in the whole file into an array of lines, then reverse the array in-memory.
I'm quite a beginner at coding and the problem that I'm having is that the procedure is too large. I read that this can be fixed by dividing the code into smaller modules. However I want to know if the values of the variables defined outside the modules can be taken into account when you call the variable inside the modules to modify it. Also, after being modified can you use the new value outside the module and in another module? Can someone explain me how the VBA works in these cases? Thank you so much.
I read the answer you gave me but while i understand the concept there is no example that fit my case. I would really appreciate an example so I can fully understand how to solve my issue. What i have is basically:
sub simulador()
Sheets(2).Activate
With ActiveSheet
a=1
b=1
c=1
for t=2 to 20
procedure using and modifying variables a and c
b=cells(t,15)
for a=2 to 20
code using variable b
next a
d=3
j=9
procedure using the variables a b and j
for ga=2 to 20
code using variable d
next ga
next t
end with
end sub
And what i need to do is create a sub1 whit:
procedure using and modifying variables a and c
b=cells(t,15)
A sub 2 whit:
for a=2 to 20
code using and modifying variable b
next a
An sub 3 whit:
procedures using the variables a b and j
for ga=2 to 20
code using variable d
next ga
So at the end would be like:
sub simulador()
Sheets(2).Activate
With ActiveSheet
a=1
b=1
c=1
for t=2 to 20
Call sub 1
Call sub 2
d=3
j=9
Call sub 3
next t
end with
end sub
In all the cases i want to call the subroutines passing the variables Byref so once they are modified stay modified so another sub can use them with the new value. Also the active sheet should remain active when the procedures in those subroutines are executed. I can't figure out how everything works exactly. Thanks for your help.
I don't have the will to spend time in explain how this works, because these are there very basics of programming, so.... search on google this:
vb function passing parameter difference byref and byval
I recently installed VS2013 (alongside a previous VS2010 installation) and noticed I no longer receive the compiler warning 'BC42324' (text below) when compiling identical VB.NET code (I recompiled back in VS2010 to confirm warning is still shown):
Using the iteration variable in a query expression may have
unexpected results. Instead, create a local variable within the loop
and assign it the value of the iteration variable.
Documentation on MSDN seems to suggest the warning is still included. I see/don't-see the warning with the following code :
Dim Numbers = {0, 1}
For Each index In Numbers
Dim SumPlusIndex = Aggregate x In Numbers Select x + index Into Sum()
Next
Has this warning genuinely been removed? Is so how come? If not could there be other environmental differences between my VS2010 and VS2013 installation that might cause the difference?
Yes, that's the infamous capture the for loop variable bug. It has bitten many programmers so Microsoft decided to do something about it. They solved it for a For Each loop, but not a For loop. You can still trigger the warning like this:
Sub Main()
For ix As Integer = 1 To 10
Dim dlg = Sub()
Console.WriteLine(ix) '' Eek!
End Sub
'' etc...
Next
End Sub