It's Making A Continuous Loop!!! What Is Wrong? - windows

Ok, so I have been given the task to create a script that can increase or decrease the volume. My problem is when I run it, and type in "Decrease" then type in "29" it goes down to 0 then starts to loop. Can you please tell me where the loop is and how to fix it?
set Keys = CreateObject("WScript.Shell") 'So The Script Can Simulate Key Presses
set oShell = CreateObject("WScript.Shell") 'So The Script Can Control The Master Volume
'Asks The User If They Wish To Increase Or Decrease The Volume
Answer = InputBox("Increase Or Decrease Volume?", "Increase/Decrease Volume:")
If Answer = "Increase" Then 'If The User Types In Increase The Following Happens
'Runs The Master Volume App.
oShell.run"%SystemRoot%\System32\SndVol.exe"
'Stops The Program For # Milliseconds
WScript.Sleep 1500
'Asks How Much To Increase The Volume By
Amount = InputBox("How Much Do You Want To Turn The Volume Up?", "Increment:")
'Pushes the Up Arrow Key The Amount Of Which The User Entered
For X = 0 To Amount Step 1
'Simulates The Pushing Of The Up Arrow
Keys.SendKeys("{Up}")
X =+ 1 'Counter Increment
Next
ElseIf Answer = "Decrease" Then 'If The User Types In Decrease The Following Happens
'Runs The Master Volume App.
oShell.run"%SystemRoot%\System32\SndVol.exe"
'Stops The Program For # Milliseconds
WScript.Sleep 1500
'Asks How Much To Decrease The Volume By
Amount = InputBox("How Much Do You Want To Turn The Volume Down?", "Decrement:")
'Pushes the Down Arrow Key The Amount Of Which The User Entered
For X = 0 To Amount Step 1
'Simulates The Pushing Of The Down Arrow
Keys.SendKeys("{Down}")
X =+ 1 'Counter Increment
Next
ElseIf Answer = "" Then 'If The User Pushes Cancel The Following Happens
Question = MsgBox("Do You Wish To Quit?",vbYesNo,"Quit:")
'If The User Pushes Yes Then The Script Will End
If Question = vbYes Then
WScript.Quit 0 'Stops The Script
End if
Else
MsgBox("The Values Allowed Are:" & vbNewLine & "Increase" & vbNewLine & "Decrease")
End If

Does VBScript have Increment Operators
X = X + 1 is the proper way of achieving what you're trying to do with X =+ 1 (which may just be setting X to 1 over and over again). In your usage however, you can take those lines out completely since the For X = 0 To Amount Step 1 should already be handling the increment for you.

There is no =+ (add and assign) operator in VBScript. Your
X =+ 1 'Counter Increment
is seen as
X = +1 ' assign +1 to X
Evidence:
>> X = 10
>> X =+ 1
>> WScript.Echo X
>>
1
You should delete those lines as the loop variable in a For To statement updates automagically.

Related

vbscript won't read file after 8Mb

I have a file written in vbs that wont read a file after about 8MB. I am currently using "Scripting.FileSystemObject". When I test the code, I notice that it runs fine until line ~79500, thats when the "AtEndOfStream" just results in True. I was looking for documentation, but it seems not to exist.
The code is supposed to show duplicate file information and put it in a separate file, which works well enough till around that line.
This is the section of code giving me the problem (it is the second reading function I have in the code):
Set first = fso.OpenTextFile(filePath + firstFileName)
Set secondFile = fso.OpenTextFile(filePath + secondFileName)
count = 0
countInLine = 0
Do Until secondFile.AtEndOfStream
lineMatches = false
lineOfSecond=secondFile.ReadLine
If count > 79440 Then
MsgBox("first line" & first.AtEndOfStream)
End If
Do Until first.AtEndOfStream
lineOfFirst =first.ReadLine
if lineOfSecond = lineOfFirst Then
lineMatches = True
Exit Do
End If
Loop
If Not lineMatches Then
writeFl.Write(count & "second" & lineOfSecond & vbCrLf)
End If
count = count + 1
Loop

slow loop when automating Excel

I need to create an excel sheet which contains a visual representation of a bit array. Presently I test the bit value and update the cell contents
For h = 1 To 128
value = Mid(array, h,1)
If value = "1" Then
xl.Application.Sheets("Sheet1").Cells(129 - h,5).value = "X"
Else
xl.Application.Sheets("Sheet1").Cells(129 - h,5).value = ""
End If
Next
If I add a WScript.Sleep 100 before Next then the output result in the excel sheet is correct.
If not, then the X's are in the wrong places.
Initially I thought that it was Excel that was slow, so I tried making a CSV file that I could simply import later, but with the same results: too fast and the X's are in the wrong positions, slow it down and they are correct.
There are around 128 of these 128bit arrays, and if each takes 3 ~ 5 seconds then making this sheet will take forever.
Does anyone know how I can achieve this quickly? I am open to other ideas/solutions (with VBS) outputting the excel file.
Thanks!
Try putting the array into the range in one go, like this
ReDim dat(1 To 128, 1 To 1)
For h = 1 To 128
v = Mid$(arr, h, 1)
dat(129 - h, 1) = IIf(v = "1", "X", "")
Next
xl.Application.Sheets("Sheet1").Cells(1, 5).Resize(128, 1).Value = dat
This worked for me (tested in vbscript rather than vba).
As it uses an array, the "" output as part of an IF is redundant as the array is blank, so it is only necessary to write the X when the bit is 1.
Dim StrArr
Dim xl
Set xl = CreateObject("excel.application")
Set wb = xl.Workbooks.Add
'sample array
StrArr = "1100111011001110110011101100111011001110110011101100111011001110110011101100111011001110110011101100111011001110110011101100111"
Dim X(128, 1 )
For lngrow = 1 To UBound(X)
If Mid(StrArr, lngrow, 1) = "1" Then X(lngrow, 0) = 1
Next
wb.Sheets(1).Cells(1, 5).Resize(UBound(X), 1).Value = X
xl.Visible = True

VBA written in Excel for Windows not working on Mac

I have a set of macros to hide and unhide columns based on the contents of a specific row. They were all written in Excel 2013 for Windows (running in parallels on my MBA, if that's relevant) and work fine there. But when I open the worksheet in Excel 2011 for Mac, the macros give odd results. The "unhide all columns" macro works fine; the other functions get as far as hiding all columns but not as far as unhiding the ones I want to see.
I can only assume Excel for Mac is having a problem with what's in the FOR EACH loop, but I can't figure out what! I'd appreciate any guidance: I need to get this system working on both Windows and Mac.
Code below.
This function works:
Sub GANTT_Filter_Show_All()
Dim rngDates As Range
Set rngDates = Range("GANTT_Dates")
rngDates.EntireColumn.Hidden = False
End Sub
But this one only hides all the columns:
Sub GANTT_Filter_This_Quarter()
Dim intCurrentMonth As Integer, intCurrentYear As Integer, rngDates As Range, cell As Range
Dim intCurrentQuarterMonths(3) As Integer
Set rngDates = Range("GANTT_Dates")
intCurrentMonth = DatePart("m", Date)
intCurrentYear = DatePart("yyyy", Date)
'loading months of current quarter into an array intCurrentMonth
Select Case intCurrentMonth
Case 1 To 3
intCurrentQuarterMonths(0) = 1
intCurrentQuarterMonths(1) = 2
intCurrentQuarterMonths(2) = 3
Case 4 To 6
intCurrentQuarterMonths(0) = 4
intCurrentQuarterMonths(1) = 5
intCurrentQuarterMonths(2) = 6
Case 7 To 9
intCurrentQuarterMonths(0) = 7
intCurrentQuarterMonths(1) = 8
intCurrentQuarterMonths(2) = 9
Case 10 To 12
intCurrentQuarterMonths(0) = 10
intCurrentQuarterMonths(1) = 11
intCurrentQuarterMonths(2) = 12
End Select
'hiding all columns
rngDates.EntireColumn.Hidden = True
'comparing each column to array of months in current quarter and hiding if false
For Each cell In rngDates
For Each v In intCurrentQuarterMonths
If v = DatePart("m", cell.Value) And DatePart("yyyy", cell.Value) = intCurrentYear Then cell.EntireColumn.Hidden = False
Next v
Next cell
Application.Goto Reference:=Range("a1"), Scroll:=True
End Sub
I'm with #Steven on this one, nothing obviously wrong with the code. I'm not a Mac user, but it's entirely possible that there's some weirdness around the date functions, particularly those that require formatting to resolve.
I would try replacing the calls to DatePart() with calls to Month() and Year() in situations like this - even for non-Mac users. It doesn't rely on parsing the strings for formatting, so it's much more efficient (and easy to read):
Sub Benchmarks()
Dim starting As Double, test As Date, i As Long
test = Now
starting = Timer
For i = 1 To 1000000
Year test
Next i
Debug.Print "Elapsed: " & (Timer - starting)
starting = Timer
For i = 1 To 1000000
DatePart "yyyy", test
Next i
Debug.Print "Elapsed: " & (Timer - starting)
End Sub
Since you likely can't run the benchmark...
Elapsed for Year(): 0.109375
Elapsed for DatePart(): 0.515625
Also note that in addition to this, the dates in the column you're searching are coming through as Variants, it may help to explicitly cast them to dates:
If v = Month(CDate(cell.Value)) And intCurrentYear = Year(CDate(cell.Value)) Then
cell.EntireColumn.Hidden = False
End If

Excel Macro, vlookup function works slow, ways to speed up macro

Hello stackexchange community.
I've built a simple tables converter, the main function of which is to convert the table from
1a Value
1b Value
1c Value
1d Value
to
a b c d
1 Value Value Value Value
Unfortunately, the macro runs pretty slow (~ 3 lines per second for one column).
I'd really appreciate if someone could take a look at my piece of code and suggest the way to speed it up.
Here's the piece of code:
Dim LastFinalList As Integer: LastFinalList = Sheet1.Range("O1000").End(xlUp).Row
For Col = 16 To 19
For c = 2 To LastFinalList
searchrange = Sheet1.Range("J:L")
lookfor = Sheet1.Cells(c, 15) & Sheet1.Cells(1, Col)
CountFor = Application.VLookup(lookfor, searchrange, 3, False)
If IsError(CountFor) Then
Sheet1.Cells(c, Col).Value = "0"
Else
Sheet1.Cells(c, Col).Value = CountFor
End If
Next c
Next Col
Thanks in advance and best regards!
UPD:
The Data in unconverted table looks like this (e.g):
Updated by Macro
Value Number Type Key Count Average Value
10 1 a 1a 2 20
30 1 a 1a 2 20
40 1 b 1b 1 40
50 1 c 1c 1 50
So it is also required to calculate averages of repeating types, create a unique list of Numbers (which is LastFinalList in my case) and finally convert it to this:
Number a b c
1 20 40 50
application.vlookupseraches by Number&Type Key, which is also assigned in the unconverted table by macro. The same time those Keys are counted, in order to calculate average for the repeating ones.
Everything works in a blink of an eye till it comes to 'to update final table part.
Full Code:
Sub ConvertToTable()
Dim LastMeter As Integer: LastMeter = Sheet1.Range("I1000").End(xlUp).Row
Sheet1.Range(Cells(2, 9), Cells(LastMeter, 9)).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Sheet1.Range("O2"), Unique:=True
Sheet1.Range("O1").Value = "The List"
Sheet1.Range("O2").Delete Shift:=xlUp
' to assign keys
For i = 2 To LastMeter
Set CountOpt = Sheet1.Cells(i, 10)
Sheet1.Cells(i, 10).FormulaR1C1 = "=r[0]c[-1]&r[0]c[-2]"
Sheet1.Cells(i, 11).FormulaR1C1 = "=COUNTIF(c10:c10, r[0]c10)"
Next i
'to calculate averages
For x = 2 To LastMeter
If Sheet1.Cells(x, 11).Value = 1 Then
Sheet1.Cells(x, 12).FormulaR1C1 = "=rc7"
ElseIf Sheet1.Cells(x, 11).Value > 1 Then
If Sheet1.Cells(x, 10).Value <> Sheet1.Cells(x - 1, 10).Value Then
Sheet1.Cells(x, 12).FormulaR1C1 = "=ROUND((SUM(rc7:r[" & Sheet1.Cells(x, 11).Value - 1 & "]c7)/" & Sheet1.Cells(x, 11).Value & "),4)"
Else
Sheet1.Cells(x, 12).FormulaR1C1 = "=r[-1]c12"
End If
End If
Next x
'to update final table
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim LastFinalList As Integer: LastFinalList = Sheet1.Cells(Rows.Count, 15).End(xlUp).Row
For Col = 16 To 19
For c = 2 To LastFinalList
searchrange = Sheet1.Range("J:L")
lookfor = Sheet1.Cells(c, 15) & Sheet1.Cells(1, Col)
CountFor = Application.VLookup(lookfor, searchrange, 3, False)
If IsError(CountFor) Then
Sheet1.Cells(c, Col).Value = "0"
Else
Sheet1.Cells(c, Col).Value = CountFor
End If
Next c
Next Col
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Sheet1.Range("O1").Select
End Sub
Also, initially i had a SUMIF formula instead of application.vlookup to be input in each cell in the converted table. But the code was working as slow as now an was bit bulky, that's why i've decide to switch to VLOOKUP.
The thing is, if it actually the way application.vlookup works (with 0.3sec delay for each row), then i guess there's nothing that can be done, and i'm ok to accept that. Although, if that's not the case, i'd really appreciate if someone could help me out and speed up the process.
Thanks!
You can redefine your LastFinalList variable something like
LastFinalList = Sheets("Sheet1").UsedRange.Rows.Count
OR
LastFinalList = Sheets("Sheet1").Cells(Rows.Count, 2).End(xlUp).Row
instead of explicitly defining used range.
Also use following line of code before your code
Application.ScreenUpdating = False
(Turn screen updating off to speed up macro code. User won't be able to see what the macro is doing, but it will run faster.)
After the whole code runs you can(optional) turn screen updating on with
Application.ScreenUpdating = True
It appears that application.vlookup in my particular case was indeed working very slow (no idea why, though). I've managed to improve macro by replacing vlookup with SUMIF formula in each cell, so now the converted table is updated instantly. Thanks everyone who participated and provided their suggestions!

QTP 10 - A function return deifferent results for same data in run and debug modes

I would extremely appreciate if anyone can suggest a solution for this.
I have a simple function that is is expecting for a browser to be opened on a page containing a web list that each value of it represents an account. When an account is selected it's products (if any) are displayed.
The functions goal is to retrieve an index of an account with products (the first to be found) or -1 if there are none.
The problem, which I can't figure out what is causing it, is that the function will return the correct result when I'm debugging it - meaning running the code step by step using F10, but will return a wrong result if I'll run regularly (F5). This behavior is consistent and the function retrieves the same result each time for each type of runs, meaning it's not a bug that just makes the function return a random answer.
This is the function:
' #return: a random account index with products if one exists
' otherwise returns -1
Public Function getRandomAccountWithProducts()
On Error Resume Next
Set Page1 = Browser("micclass:=browser").Page("micclass:=Page")
Set br = Browser("micclass:=Browser")
originalURL = br.GetROProperty("URL")
br.Navigate Environment.Value("SOME URL") & "REST OF URL"
br.Sync
Page1.WebList("name:=accountId").Select "#1"
br.Sync
' Display only products
Page1.WebRadioGroup("name:=name0").Click
Page1.WebList("name:=name1").Select "Display None"
Page1.WebList("name:=name2").Select "Display None"
Page1.WebButton("value:=Apply","visible:=True").Click
' Init
numOfAccounts = Page1.WebList("name:=accountId").GetROProperty("items count") - 1
If numOfAccounts < 1 Then
getRandomAccountWithProducts = -1
Reporter.ReportEvent micFail, "Number of accounts","There are no accounts. No account with products exists"
Exit Function
End If
hasProducts = false
accountIndex = 1
' Get account with products
While ((Not hasProducts) AND (accountIndex =< numOfAccounts))
' Return account if has products
If Page1.WebList("name:=webListName","index:=0","micclass:=WebList","visible:=True").Exist(5) Then
hasProducts = true
End If
If (Not hasProducts) Then
accountIndex = accountIndex + 1
Page1.WebList("name:=accountId").Select "#" & accountIndex
End If
Wend
br.Navigate originalURL
Set Page1= Nothing
Set br = Nothing
' If no account has products, report and exit, else return selected account index
If Not hasProducts Then
Reporter.ReportEvent micFail,"Accounts","No account has products."
getRandomAccountWithProducts = -1
Else
getRandomAccountWithProducts = accountIndex
End If
If Err<>0 Then
errorMessage = "Error number: " & Err.Number & vbNewLine & "Error description: " & Err.Description & vbNewLine & "Error source: " & Err.Source
Reporter.ReportEvent micFail,"Run Time Error",errorMessage
Err.Clear
End If
On Error GoTo 0
End Function
I'm running on Pentium 4, 3.2 GHZ, 2 GB RAM, Win XP, SP 3,IE 7, QTP 10.0 Build 513
Thanks!
Have you considered using the all items property?
AllItems = Page1.WebList("name:=accountId").GetROProperty("all items")
SplitItems = Split(AllItems, ";")
Found = False
For i = 0 To UBound(AllItems)
If AllItems(i) = "<product>" Then
Found = True
Exit For
End If
Next
Solution was found thanks to Jonty,
The problem was in the following section:
' Get account with products
While ((Not hasProducts) AND (accountIndex =< numOfAccounts))
' Return account if has products
If Page1.WebList("name:=webListName","index:=0","micclass:=WebList","visible:=True").Exist(5) Then
hasProducts = true
End If
If (Not hasProducts) Then
accountIndex = accountIndex + 1
Page1.WebList("name:=accountId").Select "#" & accountIndex
End If
Wend
The first time entered to the loop, the account really didn't have any products, so obviously none was recognized. So accountIndex was increased by one and the corresponding account was selected in the web list.
No here lies the problem. The select method caused a refresh in the page and the condition Page1.WebList("name:=webListName","index:=0","micclass:=WebList","visible:=True").Exist(5)
was evaluated before the web list was loaded thus, returning false.
I considered that option, but I thought (wrongly apparently) that the Exist(5) should do the trick, but it seems that it works differently than expected.
Thanks,
Alon

Resources