Alright, Ill try to explain this as best as I can first...
My program creates a dynamic table of information, Im trying to simplify some of the information by using a loop. To make it easy I will just say that the table starts on A1 and goes to (columnindex:rowindex*6) (that part is already done).
what I want it to do is to take the average of each column and put them somewhere else on the same excel sheet.
So Average(A1:A(rowindex*6)), Average(B1:B(rowindex*6)), and so on all the way up till Average((columnindex)1:columnindex(rowindex*6)
Now the tricky part....
Starting in A((rowindex*6)+5).... So 5 rows below the table above starting in Column A....
Have it go...
Average(A), Average(B)
Average(C), Average(D)
Average(E), Average(F)
And so on until all the columns are listed...
Where I am struggling is converting columnindex to the appropriate letters as there is always 34-40 columns
I know that I would want to do something like:
i = 5
for x = 1 to x = columnindex
dim Num2Let1 as string = a=1, b=2, c=3, so on..
dim Num2Let2 as string = a=1, b=2, c=3, so on..
xlWorkSheet2.Cells((rowindex*6)+i), 1) = "Average(" & Num2Let1.ToString & cstr(1) & ":" & Num2Let1.ToString & cstr(rowindex*6))
xlWorkSheet2.Cells((rowindex*6)+i), 2) = "Average(" & Num2Let2.ToString & cstr(1) & ":" & Num2Let2.ToString & cstr(rowindex*6))
i = i + 1
x = x + 2
loop
next
If anyone could throw some advice my way, whether this is the approach that would be most conducive to my problem, or if there is an easier solution, it would be greatly appreciated.
Thanks
Here is a function that will give you the column name based on its index:
Private Function GetExcelColumnName(columnNumber As Integer) As String
Dim col As Integer = columnNumber
Dim columnName As String = ""
Dim num As Integer
While col > 0
num = (col - 1) Mod 26
columnName = Convert.ToChar(65 + num).ToString() & columnName
col = CInt((col - num) \ 26)
End While
Return columnName
End Function
That should help you to create your average function strings.
Related
I would like to convert a range of numbers (and single digits) from a number-only format to alpha-numeric format. Entire statement is in a single, excel cell and would like the converted version to be in a neighboring cell.
As an example:
Assuming 1-24=B1-B24
Assuming 25-48=C1-C24
INPUT—
screen 1-3,5,7-9,11-30,32-37,39-40,41,44-46
DESIRED OUTPUT (all acceptable)
screen B1-B3,B5,B7-B9,B11-C6,C8-C13,C15-C16,C17,C20-C22
OR
screen B1-B3,B5,B7-B9,B11-B24,C1-C6,C8-C13,C15-C16,C17,C20-C22
OR
screen B1-B3,B5,B7-B9,B11-B24
screen C1-C6,C8-C13,C15-C16,C17,C20-C22
Using excel functions is proving quite cumbersome so excel macro would be better. I've looked for examples of requested conversion but haven't found anything.
Any help is greatly appreciated.
Cheers,
Bob
Hey here is a solution that i tested out. Not sure if "screen" needs to be in the string or not. Let me know and I will tweak it if that's the case.
Its a user defined function. So drop this vba in a module and then go to a worksheet and type in "=AlphaConvert(" + the cell reference.
Assumption here is that only one cell will be referenced at a time.
Last this could easily be converted to a sub routine and probably run a bit faster than the function.
Public Function AlphaConvert(TargetCell As Range)
Dim v As Long
Dim vArr() As String
Dim i As Long
Dim iArr() As String
Dim a As String
vArr = Split(TargetCell.Value, ",")
For v = LBound(vArr) To UBound(vArr)
If InStr(vArr(v), "-") > 0 Then
iArr = Split(vArr(v), "-")
For i = LBound(iArr) To UBound(iArr)
If i = LBound(iArr) Then
a = AlphaCode(iArr(i))
Else
a = a & "-" & AlphaCode(iArr(i))
End If
Next i
vArr(v) = a
Else
vArr(v) = AlphaCode(vArr(v))
End If
If v = LBound(vArr) Then
AlphaConvert = vArr(v)
Else
AlphaConvert = AlphaConvert & "," & vArr(v)
End If
Next v
End Function
Private Function AlphaCode(Nbr As Variant)
Select Case Nbr
Case 1 To 24
AlphaCode = "B" & Nbr
Case Else
AlphaCode = "C" & Nbr - 24
End Select
End Function
Context : I want to import in a PostgreSQL database some data that is in a Excel spreadsheet.
To do so, I have established in VBA a connection with the database, and now, I want to carry out one INSERT SQL query for each of the rows, e.g.
INSERT INTO mytable VALUES ('a','b',32,'d',17.2);
if we suppose a pgSQL table with 5 columns, 2 of them being numerical.
Using an array and the VBA join function I already figured out how to take a given line of the Excel table and convert it into a list in which every item is quoted, e.g.
('a','b','32','d','17.2');
from which I can easily write an SQL query.
The drawback of having all the items quoted is that upon inserting, the postgreSQL server will have to convert the numerical values that have been passed as strings back to numerical values again. I fear that this could impact performance, especially in situations where 50000+ lines need to be processed.
The question : In this context, I would like to find a solution to put quotes only on non-numerical values when converting a VBA array into a comma-separated list without using a For loop on the columns, which could affect performance as well.
My current VBA code to convert my horizontal Excel range into such a list is:
myArray = Application.Transpose(Application.Transpose(myRange.Value))
myList = "('" & Join(myArray, "','") & "')"
(in the above example, myArray would be a VBA array containing the values ("a","b",32,"d",17.2)).
Take a few milli-seconds to convert the array before the Join.
Dim myarray As Variant, mylist As String, i As Long
myarray = Application.Transpose(Application.Transpose(Range("a1:f1").Value2))
For i = LBound(myarray) To UBound(myarray)
If Not IsNumeric(myarray(i)) Then _
myarray(i) = Chr(39) & Trim(myarray(i)) & Chr(39)
Next i
mylist = "(" & Join(myarray, Chr(44)) & ")"
Debug.Print mylist
Use a loop with a buffer to build the SQL. You won't notice a difference on the performance. You'll also have more control over the type and you'll be able to escape the quote in case a string contains one:
Sub Test()
Dim data()
data = [{ "a",1 ; "b",2 }]
Debug.Print ToSqlInsert("MyTable (Col1, Col2)", data)
End Sub
Public Function ToSqlInsert(target As String, data()) As String
Dim sb() As String, n As Long, r As Long, c As Long
ReDim sb(0 To UBound(data, 1) * UBound(data, 2) * 2)
sb(n) = "INSERT INTO " & target & " VALUES ("
n = n + 1
For r = 1 To UBound(data, 1)
For c = 1 To UBound(data, 2)
If c > 1 Then sb(n - 1) = ","
Select Case VBA.VarType(data(r, c))
Case vbString: sb(n) = "'" & Replace$(data(r, c), "'", "''") & "'"
Case vbDate: sb(n) = Int((data(r, c) - #1/1/1970#) * 86400) ' to epoche '
Case vbEmpty: sb(n) = "NULL"
Case Else: sb(n) = data(r, c)
End Select
n = n + 2
Next
sb(n - 1) = "),("
Next
sb(n - 1) = ");"
ToSqlInsert = Join$(sb, Empty)
End Function
I have data as shown:
http://bit.ly/1O6aaWX
For each department I have to calculate minimum, maximum wait time and if possible, average time too. The no. of departments can be dynamic. I have got no clue how to do this.
Using the following as an example:
You need to use SUMIF() to get the total in column E
http://www.techonthenet.com/excel/formulas/sumif.php
In your case you need the following (row 2):
=SUMIF($B$2:$B$11,"=" & D2,$C$2:$C$11)
Then COUNTIF in column F (row 2):
https://support.office.com/en-za/article/COUNTIF-function-e0de10c6-f885-4e71-abb4-1f464816df34
=COUNTIF(B2:B11,"="&D2)
Average is obviously sum/count!
And then you can use the following information to work out the max and min ... http://www.contextures.com/excelminmaxfunction.html#minif
By placing the department name in column D, and referencing it in the SUMIF\COUNTIF forumals, you can create a list of departments as long as you want!
NOTE the MINIF example is an array formula ... best look that up first if you've never used one before ... http://www.excel-easy.com/functions/array-formulas.html
If you really must use VBA, then this will work for the example worksheet i've shown at the top of this post ...
Sub CalculateStuff()
Dim dDepartmentTotals(4) As Integer
Dim dDepartmentMinimum(4) As Integer: For i = 1 To 4: dDepartmentMinimum(i) = 32767: Next i
Dim dDepartmentMaximum(4) As Integer
Dim dDepartmentAverage(4) As Integer
Dim dDepartmentCount(4) As Integer
For i = 2 To 11
ideptno = CInt(Right(Sheets("Sheet1").Cells(i, 2), 1))
dDepartmentTotals(ideptno) = dDepartmentTotals(ideptno) + Sheets("Sheet1").Cells(i, 3)
If dDepartmentMaximum(ideptno) < Sheets("Sheet1").Cells(i, 3) Then dDepartmentMaximum(ideptno) = Sheets("Sheet1").Cells(i, 3)
If Sheets("Sheet1").Cells(i, 3) < dDepartmentMinimum(ideptno) Then dDepartmentMinimum(ideptno) = Sheets("Sheet1").Cells(i, 3)
dDepartmentCount(ideptno) = dDepartmentCount(ideptno) + 1
Next i
For i = 1 To 4
dDepartmentAverage(i) = dDepartmentTotals(i) \ dDepartmentCount(i)
Next i
End Sub
I have an extremely large dataset with customer numbers and we cannot just use a =IF(E3=160248, "YES", "NO") to tag a particular customer number of 160248 with YES or NO. Instead, I would like to use VBA code to lookup Customer_Number in column E and return a YES or NO in the corresponding row in Column AG, called Incorporated_160248. I have not done an If then clause in VBA, so I have no idea where to start. Please note, each month the data set can change. One month it could be 4,000 entries and the next 3,500, so that has to be dynamic. Any thoughts?
Sub TagTryco()
Dim CN As Integer, result As String
CN = Range("E:E").Value
If CN = 160248 Then
result = "YES"
Else
result = "NO"
End If
Range("AG:AG").Value = result
End Sub
I get a Compile error: Wrong number of arguments or invalid property assignment.
This CODE Works now:
Sub TagTryco()
Dim listLength
listLength = Worksheets("ILS_Import").Cells(Rows.Count, "E").End(xlUp).Row - 1
Dim i As Integer
For i = 2 To listLength + 2
If Worksheets("ILS_Import").Range("E" & i) = 160248 Then
Worksheets("ILS_Import").Range("AG" & i) = "Yes"
Else
Worksheets("ILS_Import").Range("AG" & i) = "No"
End If
Next
End Sub
To know how many entries you have:
dim listLength
listlength = Sheet1.Cells(Rows.Count, "E").End(xlUp).Row - 1 'I assumed column E, starting at row 2
You need to loop from row 2 to the row 2 + listLength, check the cell in column E, and check if it is equal to your number:
dim i as integer
for i = 2 to listLength + 2
If Range("E" & i) = 160248 Then
Range("AG" & i) = "Yes"
Else
Range("AG" & i) = "No"
End If
Next
If you wish to scan for different numbers you can adapt the code to use a value from a cell in which you enter that number, OR use an inputbox to enter the number you want to look for, or something else. This code was not tested.
If you want to use the column name you assigned instead of AG (which is safer) you can use something along the lines of:
= Range("Incorporated_160248")(i+1)
Instead, which gives the column with an offset of i. Should bring you to the right cell.
Dim ssi(11) As String
For i = 0 To 10
If ssi(i) = "" Then ssi(i) = "0"
For j = 0 To Val(ssi(11)) + i
ssi(i) = xuh(Val(ssi(i)))
Next
Next
If ssi(11) = "2" Then
L_zz.Caption = Val(Left(ssi(0) & ssi(1) & ssi(2) & ssi(3) & ssi(4) & ssi(5) & ssi(6) & ssi(7), ssi(10)))
ElseIf ssi(11) = "3" Then
L_zz.Caption = Val(Left(ssi(0) & ssi(1) & ssi(2) & ssi(3) & ssi(4) & ssi(5) & ssi(6) & ssi(7), ssi(10))) * (-1)
End If
I am new here and new to VB as well.
I am trying to understand this double loop in vb code.
ssi(i) is defined as a String variable. and each element is assigned to a specific number in a String. Hope I told it clearly.
My problem with this loop is below.
Since i ranges from 0 to 10, what does this j mean? Does j mean the new ssi(1-10) or another whatever number?
I think the best way to answer your question about understanding a double loop is to try looking at something simpler.
The first program I always write in each new version of BASIC that comes along is a 12 times table.
I've modified it a bit below to be a 12 x 10 table for the purpose of illustrating for you how a double loop works ... hope it helps:
For x As Integer = 1 To 12
For y As Integer = 1 To 10
Console.Write(x * y)
Console.Write(vbTab)
Next
Console.WriteLine()
Next