I am using a form that takes an item and quantity. I'm trying to create a running count that consists of the quantity (denoted as qtytxt1, qtytxt2, etc) of each item. Each item has its own quantity input field denoted with the ending number (i.e., qtytxt1 applies to item 1).
I am trying to have a cell located in (emptyRow, 27) to output the sum of the total quantity of all items inputted into the form (i.e., Item 1 qty = 2,000; Item 2 qty = 3,000; Expected Output = 5,000).
There are a total of 10 input fields for "Item/Qty," however, not all 10 fields are expected to be used. I have created a code that seems to work as I prefer, however, I would receive a sum error message when entering less than 10 items.
Dim emptyRow As Long
Dim data As Worksheet
Dim runCount As Long
Worksheets("mining history").Activate
emptyRow = WorksheetFunction.CountA(Range("i:i")) + 6
Set data = Sheets("data")
runCount = 0
If qtytxt2.Value = "" Then
qtytxt2.Value = 0
ElseIf qtytxt3.Value = "" Then
qtytxt3.Value = 0
ElseIf qtytxt4.Value = "" Then
qtytxt4.Value = 0
ElseIf qtytxt5.Value = "" Then
qtytxt5.Value = 0
ElseIf qtytxt6.Value = "" Then
qtytxt6.Value = 0
ElseIf qtytxt7.Value = "" Then
qtytxt7.Value = 0
ElseIf qtytxt8.Value = "" Then
qtytxt8.Value = 0
ElseIf qtytxt9.Value = "" Then
qtytxt9.Value = 0
ElseIf qtytxt10.Value = "" Then
qtytxt10.Value = 0
End If
If IsEmpty(Range("E:E")) Then
'Is Empty
runCount = 0
Else
' Not Empty
runCount = WorksheetFunction.Sum(qtytxt1.Value, qtytxt2.Value, qtytxt3.Value, qtytxt4.Value, qtytxt5.Value, qtytxt6.Value, qtytxt7.Value, qtytxt8.Value)
Cells(emptyRow, 27).Value = runCount
End If
You can use a loop:
Dim emptyRow As Long
Dim data As Worksheet, wsMH As Worksheet
Dim runCount As Long, n As Long, v
Set data = Sheets("data")
Set wsMH = Worksheets("mining history")
'no need to Activate...
emptyRow = wsMH.Cells(Rows.count, "I").End(xlUp).row + 1
If Application.CountA(wsMH.Range("E:E")) = 0 Then
runCount = 0
Else
'loop all the entry textboxes
For n = 1 To 10
v = Me.Controls("qtytxt" & n).Value
If Len(v) > 0 And IsNumeric(v) Then runCount = runCount + v
Next n
wsMH.Cells(emptyRow, 27).Value = runCount
End If
I suspect you need this:
If qtytxt2.Value = "" Then
qtytxt2.Value = 0
End If
If qtytxt3.Value = "" Then
qtytxt3.Value = 0
End If
etc
I have challenges in highlighting/copying alternate rows in one column and pasting it to the next column and aligned.
Here's a screenshot:
Following code assumes you have two separate tabs, SRC and DST and the range of data starts in the first cell. Will do all in a single step:
Public Sub CopyAlternate()
Dim i As Long
i = 2
While Len(Sheets("SRC").Cells(i, 1).Value) > 0
Sheets("DST").Cells(i / 2 + 1, 1).Value = Sheets("SRC").Cells(i, 1).Value
Sheets("DST").Cells(i / 2 + 1, 2).Value = Sheets("SRC").Cells(i + 1, 1).Value
i = i + 2
Wend
End Sub
You can take this code and adjust it to taste:
Sub alternate()
Dim i As Integer
Dim j As Integer
Dim n As Integer
i = 0
j = 0
n = 0
With ActiveSheet
For Each c In .Range("A4:A16")
.Cells(20 + j, 1 + i).Value = c.Value
If n = 0 Or n Mod 2 = 0 Then
i = 1
j = j
Else
i = 0
j = j + 1
End If
n = n + 1
Next c
End With
End Sub
This worked for me when rebuilding your example with letters (for faster checking).
I have created an Excel spreadsheet that extracts live data from a query in SAP GUI and paste that info back into Excel
From there, I'm opening transaction ME38 to update schedule lines based off the extracted data. I need to go to the "scheduled.." column (which I know to be "txtEKET-MENGE") and change the number shown to the "Qty Delivered" (which is a part of the extraction); however, I need to only do this on certain cells in the "Schedule..." column ("txtEKET-ETENR") [data listed on extraction as well].
When it gets to "Set grid..." it ends the function and does nothing else.
Any insight would be greatly appreciated.
Here is what I've done so far.
Set xclapp = CreateObject("Excel.Application")
Set xclwbk = ThisWorkbook
Set xclsht = xclwbk.Sheets("Sheet1")
For k = 2 To ActiveCell.SpecialCells(11).Row
For j = 1 To ActiveCell.SpecialCells(11).Column
If j = 14 Then Purch = xclsht.Cells(k, j).Value
If j = 15 Then Item = xclsht.Cells(k, j).Value
If j = 16 Then SLine = xclsht.Cells(k, j).Value
If j = 8 Then PGI = xclsht.Cells(k, j).Value
Next
myTransaction = "ME38"
Session.FindById("wnd[0]/tbar[0]/okcd").Text = "/n" & myTransaction
Session.FindById("wnd[0]").sendVKey 0
On Error Resume Next
Session.FindById("wnd[0]/usr/ctxtRM06E-EVRTN").Text = Purch
Session.FindById("wnd[0]/usr/ctxtRM06E-EVRTN").caretPosition = 10
Session.FindById("wnd[0]").sendVKey 0
Session.FindById("wnd[0]/usr/txtRM06E-EBELP").Text = Item
Session.FindById("wnd[0]/usr/txtRM06E-EBELP").caretPosition = 3
Session.FindById("wnd[0]").sendVKey 0
Session.FindById("wnd[0]/tbar[1]/btn[30]").press
Session.FindById("wnd[0]/tbar[1]/btn[2]").press
Call SelectRowOnGrid
Session.FindById("wnd[0]/mbar/menu[0]/menu[0]").Select
Session.FindById("wnd[0]").Close
On Error Resume Next
Session.FindById("wnd[1]/usr/btnSPOP-OPTION1").press
Next
End If
If Err.Number <> 0 Then
'The Excel worksheet has e.g. 3 columns of data and an error column.
xclsht.Cells(j, 21).Value = "Here is an error."
Else
xclsht.Cells(j, 21).Value = "O.K."
End If
On Error GoTo 0
The following is the Function SelectRowOnGrid.
Function SelectRowOnGrid()
Dim grid As SAPFEWSELib.GuiTableControl
Dim columnname As SAPFEWSELib.GuiTableColumn
Dim texttofind As String
Set grid = Session.FindById("wnd[0]/usr/tblSAPMM06ETC_1117/")
Set columnname = Session.FindById("wnd[0]/usr/tblSAPMM06ETC_1117/txtEKET- ETENR")
texttofind = xclsht.Cells(k, 16).Value
For k = 0 To grid.RowCount - 1
If grid.GetCellValue(k, columnname) = texttofind Then
grid.SetCurrentCell
grid.DoubleClickCurrentCell
End If
Next k
End Function
I will give you an example of how to deal with a table in SAP. In your case you use the commands for a GRID and this is not correct.
for example:
myFile = "z:\tmp\test.xlsx"
mySheet = "Test"
Set xclApp = CreateObject("Excel.Application")
Set xclwbk = xclapp.Workbooks.Open(myFile)
set xclsht = xclwbk.Sheets(mySheet)
xclApp.Visible = True
xclapp.DisplayAlerts = false
k = 1
do
set myTable = session.findById("wnd[0]/usr/ssubITEMS:SAPLFSKB:0100/tblSAPLFSKBTABLE")
if k = 1 then
'rows = myTable.RowCount
cols = myTable.Columns.Count
vRows = myTable.VisibleRowCount
for j = 0 to cols - 1
xclsht.Cells(k,j + 1).Value = myTable.columns.elementAt(j).title
next
k = k + 1
end if
for i = 0 to vRows - 1
l = 1
for j = 0 to Cols - 1
on error resume next
myVariable = trim(myTable.GetCell(i,j).Text)
if err.number <> 0 then exit for
on error goto 0
if left(right(myVariable,3),1) = "," then
myVariable = replace(myVariable, "." , "")
myVariable = replace(myVariable, "," , "")
xclsht.Cells(k,l).Value = myVariable/100
else
xclsht.Cells(k,l).Value = myVariable
end if
l = l + 1
next
if err.number <> 0 then exit for
k = k + 1
next
if err.number <> 0 then exit do
myTable.VerticalScrollbar.Position = myTable.VerticalScrollbar.Position + vRows
Loop
xclapp.ActiveWorkbook.Save
Set xclwbk = Nothing
Set xclsheet = Nothing
set xclapp = Nothing
Regards,
ScriptMan
I have a problem when I want to build a pairs trading automation using Excel VBA.
My strategy is to open a position (OTC_Sell or OTC_Buy) when the spreads of two stocks hit +/- 2 standard deviation, and to close a position (CTC_buy or CTC_sell) when the spreads of two stocks hit +/- 4 standard deviation or hit back to the mean. Once the position is closed, I can open another position once I received another open trade condition(OTC).
However, when I run the code, it seems that the loop only runs one time since I can only get one trade (highlighted in yellow).After this cell, I can only get zeros but no other trade signals. I re-run the code starting from that cell beside the original column and get another trade (highlighted in green).still, I get all zeros afterwards. Whereas I want to get all trade signals within one column.
Function SignalCTC(Price1, Price2, Mean, SD, StopLoss)
Dim i, j, k, m, n, o, p, numRows, numOTC, order, list, flag, finish
numRows = Price1.Rows.Count
Dim SignalColOTC()
ReDim SignalColOTC(numRows, 1)
Dim Price1Col()
ReDim Price1Col(numRows)
Dim Price2Col()
ReDim Price2Col(numRows)
Dim P_Ratio()
ReDim P_Ratio(numRows)
'Loop 1
For i = 1 To numRows
P_Ratio(i) = Price1(i) / Price2(i)
Next i
UpperLim = Mean + (2 * SD)
LowerLim = Mean - (2 * SD)
Count = 0
flag = 0
For i = 1 To numRows
If (Count = 0 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > LowerLim)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) > UpperLim)) Then
Count = 1
flag = 1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) < LowerLim)) Then
Count = 1
flag = -1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 1 And flag = 1 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Sell"
ElseIf (Count = 1 And flag = -1 And (P_Ratio(i) > LowerLim) And (P_Ratio(i) < Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Buy"
Else: SignalColOTC(i, 1) = "Wait&See"
End If
Next i
numOTC = 0
order = 0
list = 0
For i = 1 To numRows
If (SignalColOTC(i, 1) = "OTC_Sell") Or (SignalColOTC(i, 1) = "OTC_Buy") Then
numOTC = numOTC + 1
Else: numOTC = numOTC
End If
Next i
'Dim x
'Loop 2
Dim SignalColCTC()
ReDim SignalColCTC(numRows, numOTC)
For n = 1 To numRows
If (SignalColOTC(n, 1) = "OTC_Sell") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Sell"
For j = n + 1 To numRows
If ((P_Ratio(j) < Mean) Or (Abs(P_Ratio(j)) > (1 + StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(j, list) = "CTC_Buy"
Else: SignalColCTC(j, list) = "Wait&See"
End If
Next j
ElseIf (SignalColOTC(n, 1) = "OTC_Buy") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Buy"
For k = n + 1 To numRows
If ((P_Ratio(k) > Mean) Or (Abs(P_Ratio(k)) < (1 - StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(k, list) = "CTC_Sell"
Else: SignalColCTC(k, list) = "Wait&See"
End If
Next k
End If
Next n
'Loop 3
For o = 1 To numRows
For list = 1 To numOTC
If (SignalColCTC(o, list) = "CTC_Buy") Or (SignalColCTC(o, list) = "CTC_Sell") Then
For p = o + 1 To numRows
SignalColCTC(p, list) = "0"
Next p
End If
Next list
Next o
SignalCTC = SignalColCTC
End Function
Should this be a problem with Loop 3? I tried to put both loop 2 and loop 3 under one loop, but I get not even one trade signal but all zero this time.
Function SignalCTC(Price1, Price2, Mean, SD, StopLoss)
Dim i, j, k, m, n, o, p, numRows, numOTC, order, list, flag, finish
numRows = Price1.Rows.Count
Dim SignalColOTC()
ReDim SignalColOTC(numRows, 1)
Dim Price1Col()
ReDim Price1Col(numRows)
Dim Price2Col()
ReDim Price2Col(numRows)
Dim P_Ratio()
ReDim P_Ratio(numRows)
'Loop 1
For i = 1 To numRows
P_Ratio(i) = Price1(i) / Price2(i)
Next i
UpperLim = Mean + (2 * SD)
LowerLim = Mean - (2 * SD)
Count = 0
flag = 0
For i = 1 To numRows
If (Count = 0 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > LowerLim)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) > UpperLim)) Then
Count = 1
flag = 1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 0 And (P_Ratio(i) < LowerLim)) Then
Count = 1
flag = -1
SignalColOTC(i, 1) = "Wait&See"
ElseIf (Count = 1 And flag = 1 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Sell"
ElseIf (Count = 1 And flag = -1 And (P_Ratio(i) > LowerLim) And (P_Ratio(i) < Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Buy"
Else: SignalColOTC(i, 1) = "Wait&See"
End If
Next i
numOTC = 0
order = 0
list = 0
For i = 1 To numRows
If (SignalColOTC(i, 1) = "OTC_Sell") Or (SignalColOTC(i, 1) = "OTC_Buy") Then
numOTC = numOTC + 1
Else: numOTC = numOTC
End If
Next i
'Dim x
x=1
For Y=x to numRows
'Loop 2
Dim SignalColCTC()
ReDim SignalColCTC(numRows, numOTC)
For n = x To numRows
If (SignalColOTC(n, 1) = "OTC_Sell") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Sell"
For j = n + 1 To numRows
If ((P_Ratio(j) < Mean) Or (Abs(P_Ratio(j)) > (1 + StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(j, list) = "CTC_Buy"
Else: SignalColCTC(j, list) = "Wait&See"
End If
Next j
ElseIf (SignalColOTC(n, 1) = "OTC_Buy") Then
list = list + 1
SignalColCTC(n, list) = "OTC_Buy"
For k = n + 1 To numRows
If ((P_Ratio(k) > Mean) Or (Abs(P_Ratio(k)) < (1 - StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(k, list) = "CTC_Sell"
Else: SignalColCTC(k, list) = "Wait&See"
End If
Next k
End If
Next n
'Loop 3
For o = x To numRows
For list = 1 To numOTC
If (SignalColCTC(o, list) = "CTC_Buy") Or (SignalColCTC(o, list) = "CTC_Sell") Then
For p = o + 1 To numRows
SignalColCTC(p, list) = "0"
Next p
End If
x = p
Next list
Next o
Next Y
SignalCTC = SignalColCTC
End Function
interesting problem here. had a quick look through your code and nothing jumps out. Loop 3 seems fine to me, and didn't seem critical anyway.
maybe the logic you're implementing isn't quite what you want? I've added my commented version (no real changes except tabbing). might be a good approach for you to do similar to check loop 1 and 2 are doing what you want them to.
also, I assume mean and SD inputs are of the price ratios? why not just work them out in the function?
lastly, make sure when you're declaring variables in future you specify data types. can avoid errors and confusion down the line. e.g. 'dim i as integer'
Function SignalCTC(Price1, Price2, Mean, SD, StopLoss)
Dim i, j, k, m, n, o, p, numRows, numOTC, order, list, flag, finish
numRows = Price1.Rows.Count
Dim SignalColOTC()
ReDim SignalColOTC(numRows, 1)
Dim Price1Col()
ReDim Price1Col(numRows)
Dim Price2Col()
ReDim Price2Col(numRows)
Dim P_Ratio()
ReDim P_Ratio(numRows)
'calculate ratios
For i = 1 To numRows
P_Ratio(i) = Price1(i) / Price2(i)
Next i
UpperLim = Mean + (2 * SD)
LowerLim = Mean - (2 * SD)
Count = 0
flag = 0
'Loop 1
'identify possible opening events
For i = 1 To numRows
'if no events (within limits), reset
If (Count = 0 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > LowerLim)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "Wait&See"
'if exceeds for the first time
ElseIf (Count = 0 And (P_Ratio(i) > UpperLim)) Then
Count = 1
flag = 1
SignalColOTC(i, 1) = "Wait&See"
'if under limit for the first time
ElseIf (Count = 0 And (P_Ratio(i) < LowerLim)) Then
Count = 1
flag = -1
SignalColOTC(i, 1) = "Wait&See"
'if already exceeded once and now within limits
ElseIf (Count = 1 And flag = 1 And (P_Ratio(i) < UpperLim) And (P_Ratio(i) > Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Sell"
'if were under limit once and now within limits
ElseIf (Count = 1 And flag = -1 And (P_Ratio(i) > LowerLim) And (P_Ratio(i) < Mean)) Then
Count = 0
flag = 0
SignalColOTC(i, 1) = "OTC_Buy"
Else
SignalColOTC(i, 1) = "Wait&See"
End If
Next i
numOTC = 0
order = 0
list = 0
'count opening events
For i = 1 To numRows
If (SignalColOTC(i, 1) = "OTC_Sell") Or (SignalColOTC(i, 1) = "OTC_Buy") Then
numOTC = numOTC + 1
Else
'numOTC = numOTC 'redundant, don't need
End If
Next i
'Loop 2
'identify closing events
Dim SignalColCTC()
ReDim SignalColCTC(numRows, numOTC)
For n = 1 To numRows
If (SignalColOTC(n, 1) = "OTC_Sell") Then
list = list + 1 'scroll to next column
SignalColCTC(n, list) = "OTC_Sell" 'we know this is the sale event
For j = n + 1 To numRows 'remaining rows
'if hits mean, or makes a big loss
If ((P_Ratio(j) < Mean) Or (Abs(P_Ratio(j)) > (1 + StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(j, list) = "CTC_Buy" 'close position
Else
SignalColCTC(j, list) = "Wait&See"
End If
Next j
ElseIf (SignalColOTC(n, 1) = "OTC_Buy") Then 'logic repeated for sale
list = list + 1
SignalColCTC(n, list) = "OTC_Buy"
For k = n + 1 To numRows
If ((P_Ratio(k) > Mean) Or (Abs(P_Ratio(k)) < (1 - StopLoss) * Abs(P_Ratio(n)))) Then
SignalColCTC(k, list) = "CTC_Sell"
Else
SignalColCTC(k, list) = "Wait&See"
End If
Next k
End If
Next n
'Loop 3
'just filling zeros after position is closed
For o = 1 To numRows
For list = 1 To numOTC
If (SignalColCTC(o, list) = "CTC_Buy") Or (SignalColCTC(o, list) = "CTC_Sell") Then
For p = o + 1 To numRows
SignalColCTC(p, list) = "0"
Next p
End If
Next list
Next o
SignalCTC = SignalColCTC
End Function
EDIT:
Looking through the procedure, I expect the output matrix will look something like:
SignalColCTC:
OTC_Buy Null Null
Wait&See Null Null
Wait&See OTC_Sell Null
Wait&See Wait&See Null
CTC_Sell Wait&See Null
0 CTC_Buy OTC_Buy
0 0 Wait&See
(N.B. I think nulls become zeros later)
Which seems reasonable to me. Maybe what you are trying to do is transform the pairs into a single column? It seems in the image you uploaded that this is what you want.
In the worksheet called "EIRP LL", Range L6:O13 contains data. Sometimes, rows 7-13 get hidden for reasons unrelated to this data. The data in Range L6:O13 shall remain unhidden, so the data in L6:O13 is copied into an array called ConfigDataArray. Range L6:O13 is then cleared. All of this code works.
Then, the difficulty begins. The data that is stored in ConfigDataArray must be written to the non-hidden rows beginning with Row 6, which happens to always be unhidden. I have attempted to do this by slicing the rows of the array and iterating through these rows with a For loop. But it doesn't work. Only the 1st and 3rd rows of the array data get written back into the worksheet, and the third row gets written into a hidden row. The code beginning with j = 6 and ending with Next, clearly is faulty. Any suggestions greatly appreciated.
Sub HideLLRows()
'Hide blank rows in EIRP LL
'Where blank row is defined as no data in Col B for the given row
Application.ScreenUpdating = False
Dim ConfigDataArray As Variant
Set EIRPLL = Sheets("EIRP LL")
LastLLRow = EIRPLL.UsedRange.Rows.Count
'Put the metadata into an 8Row x 4Col array for safe keeping
ConfigDataArray = Range("L6:O13").Value
'Clear the metadata cells
Range("L6:O13").Clear
'Hide the blank rows
For i = 6 To LastLLRow
If EIRPLL.Range("B" & i) = "" Then
EIRPLL.Rows(i).Hidden = Not EIRPLL.Rows(i).Hidden
End If
Next
'Slice the 8 array rows and put into the first 8 non-hidden rows
'beginning on L6:O6 (which is always non-hidden)
j = 6
For k = 1 To 8
If Rows(j).Hidden = False Then
If k < 9 Then
EIRPLL.Range("L" & k + 5) = Application.Index(ConfigDataArray, k, 1)
EIRPLL.Range("M" & k + 5) = Application.Index(ConfigDataArray, k, 2)
EIRPLL.Range("N" & k + 5) = Application.Index(ConfigDataArray, k, 3)
EIRPLL.Range("O" & k + 5) = Application.Index(ConfigDataArray, k, 4)
End If
End If
k = k + 1
j = j + 1
Next
Application.ScreenUpdating = True
End Sub
Sub HideLLRows()
Dim ConfigDataArray As Variant, i, k, j
Dim EIRPLL As Worksheet, LastLLRow
Set EIRPLL = Sheets("EIRP LL")
LastLLRow = EIRPLL.UsedRange.Rows.Count
Application.ScreenUpdating = False
'Clear the metadata cells
With EIRPLL.Range("L6:O13")
ConfigDataArray = .Value
.Clear
End With
'Hide the blank rows
For i = 6 To LastLLRow
If EIRPLL.Range("B" & i) = "" Then
EIRPLL.Rows(i).Hidden = True
End If
Next
k = 1
j = 6
Do While k <= 8
With EIRPLL.Rows(j)
If Not .Hidden Then
.Cells(12).Value = ConfigDataArray(k, 1)
.Cells(13).Value = ConfigDataArray(k, 2)
.Cells(14).Value = ConfigDataArray(k, 3)
.Cells(15).Value = ConfigDataArray(k, 4)
k = k + 1
End If
End With
j = j + 1
Loop
Application.ScreenUpdating = True
End Sub