I have a query to get the MAX recordId from the table in SQL. I then put the value in an array and add 1 to the variable. I then use the variable to create the recordId in SQL. How do I increase the recordId by 1 for each loop?
query3 = "SELECT MAX(tbl_eInvoice_Main.RecordID) AS RecordID, " & _
"MAX(tbl_ImportDate.toolImportId) As toolImportId FROM tbl_eInvoice_Main " & _
"INNER JOIN tbl_ImportDate ON tbl_eInvoice_Main.ToolImportID = tbl_ImportDate.ToolImportID;"
rs.Open query3, con, adOpenStatic, adLockReadOnly, adCmdText
arr = rs.GetRows(1)
RecordID = arr(0, 0) + 1
ToolImportId = arr(1, 0) + 1
Worksheets("DATA").Activate
Dim rng As Range: Set rng = Application.Range("A2:IP1000")
Dim row As Range
For Each row In rng.Rows
query2 = "INSERT INTO tbl_eInvoice_Main (RecordID) values (" & RecordID & ")"
con.Execute query2
Next row
You could move your RecordID logic inside the loop like this:
For Each row In rng.Rows
arr(0, 0) = arr(0, 0) + 1
query2 = "INSERT INTO tbl_eInvoice_Main (RecordID) values (" & arr(0, 0) & ")"
con.Execute query2
Next row
However, this approach won't work well if you have multiple users. Just something to keep in mind.
In the excel file as above, I want each words in the Column one (12 totally) and each words in the Column two (4 totally) to be combined into phrases generated in the Column three. I should get 12*4 = 48 phrases. Using the codes I wrote as below, only less than 30 are there with some null-value cells. Please tell me why I couldn't reach 48. Thank you.
Sub WordsCombiner()
For i = 1 To 12
For m = 1 To 4
Cells(i * m, 3).Value = Cells(i, 1).Value + Cells(m, 2).Value
Next
Next
End Sub
The following is the original words:
(Column one)
from
the
on
this
Oh
and
FYI
prices
accurate
and
items
in
Column Two
as
time
of
publication
Try this instead:
Sub WordsCombiner()
Dim i As Long
For i = 1 To 12
Dim j As Long
For j = 1 To 4
Dim k As Long
k = k + 1
Cells(k, 3).Value = Cells(i, 1).Value & " " & Cells(j, 2).Value
Next
Next
End Sub
This is dynamic so it will run for every value in Column A and Column B. It also ads the space between the groupings as you have shown in your output.
lra = last row column a
lrb = last row column b
i = counter for column c
Sub Combine()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim lra As Long, lrb As Long, a As Long, b As Long
Dim i As Long: i = 1
lra = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
lrb = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
For b = 1 To lrb
For a = 1 To lra
ws.Range("C" & i) = ws.Range("A" & a) & Chr(32) & ws.Range("B" & b)
i = i + 1 '<--Next Row on Column C
Next a
i = i + 1 '<--Add Space Between Groupings
Next b
End Sub
The logic for assigning the result row is wrong. When you have i * m you get that for both "from time" and "the as" since 1*2 and 2*1 both = 2. Either use a separate counter variable or change the expression. Best way to figure this out is define three sets of values and the row they should be and find what fits.
I would prefer SQL for that task.
Select
t1.Col1, t2.col2 , t1.col1 & " " & t2.col2
FROM
(Select col1 From [Sheet1$] WHERE col1 Is Not Null) as t1,
(Select col2 From [Sheet1$] WHERE col2 Is Not Null) as t2
That query creates a carthesian product of both columns-
The result contains all combination of column1 and column2.. If the columns contain dupes and you dön't want repeating results, just use
Select Distinct t1.col1 & " " & t2.col2 As Result ...
to get rid of them.
Here's an Example, to convince the downvoter and the loopers of the simple beautiness of SQL when working with data:
Private Sub ComputeCarthesianProduct()
Dim sql As String
sql = "Select t1.[F1] & ' ' & t2.[F2] As Result FROM " _
& " (Select [F1] From [Sheet1$] WHERE [F1] Is Not Null) as t1," _
& " (Select [F2] From [Sheet1$] WHERE [F2] Is Not Null) as t2"
Debug.Print sql
Dim con As Object
Set con = CreateObject("ADODB.Connection")
With con
.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;Imex=1;HDR=no"";"
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
With rs
.Open sql, con
Sheet1.Range("C1").CopyFromRecordset rs 'Sheet1 is CodeName of Worksheets("Sheet1"). An explicit reference, immune to renaming the sheet
.Close
End With
.Close
End With
End Sub
If you still prefer to nest one loop for each column, you deserve to get dizzy ;)
Below code is counting a final amount of students in a school and average amount of students in a class.
It's running the code until the user types "0".
How can I ensure that the "0 class" won't be counted as an additional class? Currently I am achieving it by subtracting -1 from B, but it's not an elegant solution - calculation is correct, but the class is still listed in final MsgBox.
Btw, if I wanted to end the loop when user is leaving the cell empty, what should I do? Simple Loop Until Zak = "" doesn't work.
Many thanks,
Sub D1()
Dim Zak As Byte
Dim B As Byte, C As Byte
Dim kzak As String
Dim ktrid
Dim trid As Byte
Dim k, l As Integer
B = 0
kzak = ""
Do
Zak = InputBox("Amount of students")
B = B + 1
kzak = kzak & Str(B) & (" class") & (" ") & _
("Students ") & Str(Zak) & Chr(10)
k = k + Zak
Loop Until Zak = 0
C = (B - 1)
l = k / C
MsgBox kzak & Chr(10) & ("At school is ") & Str(k) & (" students") & _
(", on avarage ") & Str(l) & (" in a class")
End Sub
This is a late post, but here is code to accomplish all the requirements you stated with just a few tweaks to your existing code:
Public Sub D2()
Dim Zak As String
Dim B As Integer
Dim kzak As String
Dim k As Integer
Dim l As Integer
B = 0
kzak = ""
Do
Zak = InputBox("Amount of students")
If Val(Zak) > 0 Then
B = B + 1
kzak = kzak & Str(B) & (" class") & (" ") & ("Students ") & Zak & Chr(10)
k = k + Val(Zak)
End If
Loop Until Zak = ""
If B > 0 Then
l = k / B
MsgBox kzak & Chr(10) & ("At school is ") & Str(k) & (" students") & (", on avarage ") & Str(l) & (" in a class")
End If
End Sub
Notice some of the changes I made.
First, I declared the variables more appropriately. Also, with your code k would have been a variant.
Second, I was able to remove the B - 1 hack while also assuring `B' had a value to avoid a divide by zero error.
Third, this code handles Cancel from the InputBox.
A common approach to this is to ask first, and then test with a Do While instead of a Loop Until, and then ask again. Something like this:
Zak = InputBox("Amount of students")
Do While Zak <> 0
...
...
Zak = InputBox("Amount of students")
Loop
I am running into an issue that is driving me crazy. I have two FOR loops in my macro that each have a counter to keep track of how many times a certain process was performed. The counters work great and at the end of the loop contain the correct numbers. The next thing I have to do is to format the counts into a five digit number with leading zeros. I have tried this using two different approaches (see below).
cCount = String(5 - Len(cTemp), "0") & cTemp
mCount = String(5 - Len(mTemp), "0") & mTemp
or
cCount = Format(cTemp, "00000")
mCount = Format(mTemp, "00000")
The problem is with the second counter. As I step through it, the first format formula works, but the second line does not, regardless of which version above that I use. Now here is the thing, if, while I am still in the macro, I go and change the name of mCount to anything else, for example mCnt, and then move the macro step back up to reprocess that line, it will correctly format the variable. But it isn't the name, because if I then run the macro again using mCnt, it will do the same thing. I can change it back to mCount and it will work.
All variables are dimmed as Integers. An example of what I am looking for would be if mTemp is 15, then mCount would be 00015. However, mCount is just coming back as 15. cCount is working fine.
The fact that everything is correct and that I can make it work if I pause the macro, change the variable name, and reprocess the line, has got me completely at a loss as to what the issue is.
Sub MakePay()
Dim strFileToOpen As String
Dim payDate, payTab, payCheckTemp, payCheck, payAccTemp As String
Dim payAcc, payAmount, payTotalC, payTotalM As String
Dim savePath As String
Dim payFileNameCLP, payFileNameMF As String
Dim payString1, payString2, payString3, payString4, payString5, payString6 As String
Dim payString7, payString8, payString9 As String
Dim rCnt, i, j, cTemp, cCount, mTemp, mCount As Integer
Dim payTotalMTemp, payAmountTemp, payTotalCTemp As Double
' Set date
payDate = Format(Now(), "yyyymmddhhmmss")
' Ask for check number and format to field length
payCheckTemp = InputBox("Please enter the check number.")
payCheck = payCheckTemp & String(15 - Len(payCheckTemp), " ")
' Create file names and open text files for writing
payFileNameCLP = "CLP_" & payDate & "_01.txt"
payFileNameMF = "MDF_" & payDate & "_01.txt"
savePath = Environ("USERPROFILE") & "\Desktop\"
Open savePath & payFileNameCLP For Output As #1
Open savePath & payFileNameMF For Output As #2
' Build header rows and print them
payString1 = "100"
payString2 = "200 C"
Print #1, payString1
Print #1, payString2
Print #2, payString1
Print #2, payString2
' reset counters for number of claims and total dollar amounts in files
cTemp = 0
mTemp = 0
payTotalCTemp = 0
payTotalMTemp = 0
For i = 1 To Sheets.Count
' Process the Clearpoint tab
If Left(Sheets(i).Name, 3) = "CLE" Then
Sheets(i).Activate
rCnt = Cells(Rows.Count, 1).End(xlUp).Row
For j = 3 To (rCnt - 1)
' Read accession # and format it for field length
payAccTemp = Cells(j, 3).Value
payAcc = payAccTemp & String(17 - Len(payAccTemp), " ")
' Read payment amount, if $0, skip
payAmountTemp = Format(Cells(j, 5).Value2, "#,###.00")
If payAmountTemp = "" Then
GoTo SkipCDL
End If
' Add payment to total Clearpoint payments
payTotalCTemp = payTotalCTemp + payAmountTemp
' Format payment by deleting decimal and then format to field length
payAmount = Format(payAmountTemp * 100, "0000000;-000000")
' Build payment strings and print them
payString3 = "400" & String(10, " ") & payAcc & payCheck
payString4 = "450" & String(10, " ") & payAcc & String(150, " ") & payAmount
payString5 = "500" & String(10, " ") & payAcc & String(73, " ") & payAmount
Print #1, payString3
Print #1, payString4
Print #1, payString5
' Increase Clearpoint patient count
cTemp = cTemp + 1
SkipCDL:
Next j
' Process Medfusion tab
ElseIf Left(Sheets(i).Name, 3) = "MED" Then
Sheets(i).Activate
rCnt = Cells(Rows.Count, 1).End(xlUp).Row
For j = 3 To (rCnt - 1)
' Read accession # and format it for field length
payAccTemp = Cells(j, 3).Value
payAcc = payAccTemp & String(17 - Len(payAccTemp), " ")
' Read payment amount, if $0, skip
payAmountTemp = Format(Cells(j, 5).Value2, "#,###.00")
If payAmountTemp = "" Then
GoTo SkipMDF
End If
' Add payment to total Medfusion payments
payTotalMTemp = payTotalMTemp + payAmountTemp
' Format payment by deleting decimal and then format to field length
payAmount = Format(payAmountTemp * 100, "0000000;-000000")
' Build payment strings and print them
payString3 = "400" & String(10, " ") & payAcc & payCheck
payString4 = "450" & String(10, " ") & payAcc & String(150, " ") & payAmount
payString5 = "500" & String(10, " ") & payAcc & String(73, " ") & payAmount
Print #2, payString3
Print #2, payString4
Print #2, payString5
' Increase Medfusion count
mTemp = mTemp + 1
SkipMDF:
Next j
End If
Next i
' Format patient counter and total payment to field length
cCount = Format(cTemp, "00000")
mCount = Format(mTemp, "00000")
payTotalC = Format(payTotalCTemp * 100, "000000000;-00000000")
payTotalM = Format(payTotalMTemp * 100, "000000000;-00000000")
' Build footer strings and print them
payString6 = "800" & String(26, " ") & "9999" & cCount & String(131, " ") & payTotalC
payString7 = "800" & String(26, " ") & "9999" & mCount & String(131, " ") & payTotalM
payString8 = "900" & String(57, " ") & "099990" & cCount & String(154, " ") & String(2, "0") & payTotalC
payString9 = "900" & String(57, " ") & "099990" & mCount & String(154, " ") & String(2, "0") & payTotalM
Print #1, payString6
Print #2, payString7
Print #1, payString8
Print #2, payString9
' Close all files
Application.DisplayAlerts = False
Close #1
Close #2
Application.DisplayAlerts = True
End Sub
The issue is with how the variables are declared.
In VBA/classic vb, all declarations should be on their own line OR have the correct data type specified, otherwise you risk accidentally creating a Variant data type, which can masquerade as any other data type, which the VB engine has rules for determining the type.
See https://msdn.microsoft.com/en-us/library/56ht941f(v=vs.90).aspx
Also, whenever coding in VBA make sure Option Explicit is declared at the top of any new code module. It will save you loads of pain in the future.
Also, you are trying to push String formatting into an Integer, which cannot happen.
So...
Option Explicit
.....
'Dim i, j as Integer 'BAD i is a variant, j is an integer
Dim i As Integer
Dim j As Integer 'GOOD both are Integers
'OR
Dim x As Integer, y as Integer 'I believe this will work too
dim displayI as String
i = 23
displayI = Format(i, "00000")
In your code why not just format inline?
payString6 = "800" & String(26, " ") & "9999" & Format(cCount,"00000") & String(131, " ") & payTotalC
pretty new with VBA and there doesnt seem to be much help around the internet as I understand it is relativley old.
I am trying to use a Macro to submit data from an excel sheet into a SQL server DB.
Basically the click of a button, should pull the required data from the cells, which then put the data in the correct columns in my DB.
It is not submitting the data properley, for example one cell has the number '2' in it and it is submitting the number '0' into my database.
Can anyone advise?
Code below.
' Create the connection string.
sConnString = "provider=xxx; Data Source=xx-xxx; Initial Catalog=xxx;User ID= xx; Password=xxx;": MsgBox "Connection Succesful"
' Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
Dim val As String
val = Range("D5").Value
' Open the connection and execute.
conn.Open sConnString
Dim item As String
item = "INSERT INTO [Industrial].[dbo].[Header]("
item = item & " [server_name]"
item = item & " ,[date]"
item = item & " ,[amendee]"
item = item & " ,[ip_address]"
item = item & " ,[physical_location]"
item = item & " ,[host_name]"
item = item & " ,[is_it_contact]"
item = item & " ,[businesscontact]"
item = item & " ,[businessdependencies]"
item = item & " ,[backup_strategy_in_place]"
item = item & " ,[physorvirt]"
item = item & " )Values("
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
item = item & " '" & val & "'"
conn.Execute item
End Sub
You may want to check the data types and the constraints on your DB table. Its possible depending on your db type (MySQL, MSSQL, or Postgres) that if you're trying to put in a 'true' instead of true for a boolean column, it will default to 0.
Secondly, I notice is that you're placing the same value into every column.
Might I suggest an array. (intro to excel vba Arrays: http://excelvbatutor.com/vba_chp21.htm)
The below code will work assuming your data is on Sheet1 and like so...
A B (columns)
1
2 column_name_B "fifty"
3 column_name_C 10
4 column_name_D myName
(rows)
Sub testeroo()
Dim myArray(2, 2)
Dim x As Integer
Sheets("Sheet1").Activate
For x = 2 To 4
myArray(x - 2, 0) = Cells(x, 1).Value 'gets the title
myArray(x - 2, 1) = Cells(x, 2).Value 'gets the value
Next x
Then you could do a loop through the array to get your SQL statement.
End Sub