I am testing a sample VB6 application which inserts text from TextBox to Excel.
I would like to find the last used row in the column, and append text from txt1 TextBox at the next row whenever user clicks a button.
The range is from C10 to C49.
After the last row is filled, I will prompt user to open new Excel file.
I am unable to do the appending part. Below is the code I tried:
Private Sub cmdUpdate_Click()
Dim objConn As New ADODB.Connection
Dim szConnect As String
szConnect = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Excel\Format.xls;" & _
"Extended Properties='Excel 8.0;HDR=NO';"
objConn.Open szConnect
Dim xrow As Integer
Dim lastRow As Integer
lastRow = 10
xrow = 49
Do while lastRow <= xrow
objConn.Execute "UPDATE [Sheet1$C" & lastRow & ":C" & lastRow & "] SET F1 =" & txt1.Text & ";"
lastRow = lastRow + 1
Loop
End Sub
The code fills the whole range on each update. I know where my mistake is, but can't figure out proper way. How to make it insert only once until row 49?
Using Excel Object model is not an option as I want to be able to make updates when workbook is open in Excel.
Simple way to achieve this would be to declare your lastRow as more visible (e.g. as private member of your form class), drop looping, and increment lastRow only once per update:
Private lastRow As Integer
'...
objConn.Execute _
"UPDATE [Sheet1$C" & lastRow & ":C" & lastRow _
& "] SET F1 =" & txt1.Text & ";"
lastRow = lastRow + 1
If you assume no complete control over the target Excel range (e.g. data in the range may be modified between your updates, and you do not wish to overwrite those changes) then you could search for the first empty cell before every update. Use IsNull() to test for empty cells.
Private Const RANGE_IS_FULL As Long = -1
' Returns first vacant position in sRange Excel range (zero-based)
' Returns RANGE_IS_FULL if no vacant position was found
' sConnectionString: connection string to Excel workbook
' sRange: Excel range of a form [Sheet1$C10:C49]
Private Function GetNextAppendPosition(sConnectionString As String _
, sRange As String) As Long
Dim lRow As Long
Dim oRS As ADODB.Recordset
Set oRS = New ADODB.Recordset
oRS.CursorLocation = ADODB.adUseClient
oRS.Open "SELECT F1 FROM " & sRange _
, sConnectionString
oRS.MoveFirst
GetNextAppendPosition = RANGE_IS_FULL
lRow = -1
While Not oRS.EOF
lRow = lRow + 1
If IsNull(oRS.Fields(0).Value) Then
GetNextAppendPosition = lRow
GoTo hExit
End If
oRS.MoveNext
Wend
hExit:
oRS.Close
End Function
With this in mind, your update routine could be coded as this:
Public Sub ExportTextToExcelRow(sText As String)
Const CONNECTION_STRING As String = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\src\Excel ADO\Book1.xls;" & _
"Extended Properties='Excel 8.0;HDR=NO'; "
Const MAX_TARGET_ROW As Long = 49
Const MIN_TARGET_ROW As Long = 10
Const TARGET_COL As String = "C"
Const TARGET_SHEET As String = "Sheet1"
Dim lRow As Long
Dim oConn As New ADODB.Connection
Dim sTargetRange As String
sTargetRange = "[" & TARGET_SHEET & "$" & TARGET_COL & MIN_TARGET_ROW _
& ":" & TARGET_COL & MAX_TARGET_ROW & "]"
lRow = GetNextAppendPosition(CONNECTION_STRING, sTargetRange)
If lRow = RANGE_IS_FULL Then
MsgBox "Oops, range is full."
Exit Sub
End If
lRow = lRow + MIN_TARGET_ROW
sTargetRange = "[" & TARGET_SHEET & "$" & TARGET_COL & lRow _
& ":" & TARGET_COL & lRow & "]"
oConn.Open CONNECTION_STRING
oConn.Execute "UPDATE " & sTargetRange & " SET F1 = """ & sText & """;"
oConn.Close
End Sub
Call it from your event handler this way:
Private Sub cmdUpdate_Click()
ExportTextToExcelRow txt1.Text
End Sub
Related
I have a UserForm that enables users to enter data into a worksheet.
A serial number is created for each row of data based on 2 ComboBox selection and 0001 at the end.
For example, MAPR0001 where MA comes from a ComboBox and PR from another one and at the end 0001 is added and is incremented for another selection of MA and PR. (MAPR0002)
Then I have a second UserForm that should allow me to update my database.
Upon selection of a serial number from a ComboBox the second UserForm pulls back the data from the worksheet to some TextBoxes.
Till here everything works fine.
But I fail to add data to a specific serial number.
My code for the command button:
Private sub Commandbuttonclick ()
If Me.ComboBox1.Value = "" Then
MsgBox "Request No. Can Not be Blank", vbExclamation, "Request No."
Exit Sub
End If
requestno = Me.ComboBox1.Value
Sheets("DASHBOARD").Select
Dim rowselect As Double
rowselect = Me.combobox1.Value
rowselect = rowselect + 1
Rows(rowselect).Select
Cells(rowselect, 2) = Me.TextBox1.Value
Cells(rowselect, 3) = Me.TextBox2.Value
Cells(rowselect, 4) = Me.TextBox3.Value
Use the WorksheetFunction.Match method to find your serial number that you want to update. Match returns the row number that you could use instead of rowselect to write your data.
For example something like this:
Dim MySerial As String
MySerial = "MAPR0001" 'adjust to your needs
Dim MyLookupRange As Range
Set MyLookupRange = Sheets("DASHBOARD").Range("A:A") 'adjust to where your serials are
Dim RowToUpdate As Long
On Error Resume Next 'next line throws error if serial not found
RowToUpdate = WorksheetFunction.Match(MySerial, MyLookupRange, 0)
On Error Goto 0 'always re-enable error reporting!
If RowToUpdate > 0 Then
'serial found, update here eg …
'Sheets("DASHBOARD").Cells(RowToUpdate, 2) = Me.TextBox1.Value
Else
MsgBox "Serial " & MySerial & " was not found."
End If
There are a few ways to do this. Here is one option for you to try.
'Private Sub Worksheet_Change(ByVal Target As Range)
Sub ImportDataFromExcel()
Dim rng As Range
Dim r As Long
Dim conn As ADODB.Connection
Dim strConn As String
Dim strSQL As String
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
"C:\Users\Ryan\Desktop\Coding\Integrating Access and Excel and SQL Server\Access & Excel & SQL Server\" & _
"EXCEL AND ACCESS AND SQL SERVER\Excel & Access\Select, Insert, Update & Delete\Northwind.mdb"
Set conn = New ADODB.Connection
conn.Open strConn
With Worksheets("Sheet1")
lastrow = .Range("A2").End(xlDown).Row
lastcolumn = .Range("A2").End(xlToRight).Column
Set rng = .Range(.Cells(lastrow, 1), .Cells(lastrow, lastcolumn))
End With
'therow = 1
For i = 2 To lastrow
'r = rng.Row
'If r > 1 Then
strSQL = "UPDATE PersonInformation SET " & _
"FName='" & Worksheets("Sheet1").Range("B" & i).Value & "', " & _
"LName='" & Worksheets("Sheet1").Range("C" & i).Value & "', " & _
"Address='" & Worksheets("Sheet1").Range("D" & i).Value & "', " & _
"Age=" & Worksheets("Sheet1").Range("E" & i).Value & " WHERE " & _
"ID=" & Worksheets("Sheet1").Range("A" & i).Value
conn.Execute strSQL
'End If
'r = r + 1
Next i
conn.Close
Set conn = Nothing
End Sub
This is for illustration purposes only. Please change to suit your specific needs.
I have a list of files in a worksheet, that are files in a subfolder of the current directory.
I need to retrieve the value of a specific cell (can change), in a specific sheet (constant).
Of 10 files that are in the subfolder and which all have a sheet called "resumen", I want to get the value of the last row in column G.
So far I have this
Sub read_data_from_file_WO_openning()
Dim outputs_address As String
Dim FolderName As String, wbName As String, cValue As Variant
outputs_address = Sheets("lista_macro").Range("G2").Value
ruta_csv_output = ActiveWorkbook.Path & outputs_address
FolderName = ruta_csv_output
'select files to review
For Each file_analysis In Sheets("archivos_en_outputs").Range("I2", Range("I2").End(xlDown))
wbName = file_analysis.Value
cValue = GetInfoFromClosedFile2(FolderName, wbName, "resumen", "G1")
MsgBox (file_analysis & cValue) 'to see the values
Next file_analysis
End Sub
Private Function GetInfoFromClosedFile2(ByVal wbPath As String, _
wbName As String, wsName As String, cellRef As String) As Variant
Dim arg As String
If Right(wbPath, 1) <> "\" Then wbPath = wbPath & "\"
arg = "'" & wbPath & "[" & wbName & "]" & _
wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1)
GetInfoFromClosedFile2 = ExecuteExcel4Macro(arg)
End Function
In range I2 to down I have my list of files.
The problem is that my "G1" only retrieves data of cell G1 of all files, and I need the last row of column G for each file.
Sometimes these files have 7 rows, others have 15. The number of rows can change but always is at least 2.
I know the problem is in cell reference, but I don't know how to change this to accomplish what I have said.
Assuming that there are no blank spaces in Column G, you can use ExecuteExcel4Macro with the WorksheetFunction CountA to find the last row.
Function getLastValueInColumnG(ByVal wbPath As String, wbName As String, wsName As String) As Variant
Dim count As Long
Dim Address As String
Address = getExternalR1C1Address(wbPath, wbName, wsName, "G:G")
count = ExecuteExcel4Macro("CountA(" & Address & ")")
Address = getExternalR1C1Address(wbPath, wbName, wsName, "G" & count)
getLastValueInColumnG = ExecuteExcel4Macro(Address)
End Function
Function getExternalR1C1Address(ByVal wbPath As String, wbName As String, wsName As String, cellRef As String) As String
If Right(wbPath, 1) <> "\" Then wbPath = wbPath & "\"
getExternalR1C1Address = "'" & wbPath & "[" & wbName & "]" & wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1)
End Function
Another approach assuming you have limited number of rows in your output files (<1000 ?)
Option Explicit
Sub find_in_closed_files()
Application.ScreenUpdating = False
Dim Fch As Range
Dim Wb1 As Workbook: Set Wb1 = ActiveWorkbook
Dim Fld As String: Fld = Wb1.Path & Sheets("lista_macro").Range("G2").Value
If Not Right(Fld, 1) = "\" Then Fld = Fld & "\"
Dim Ws1 As Worksheet: Set Ws1 = Wb1.Sheets(1)
Dim Ws2 As Worksheet: Set Ws2 = Wb1.Sheets("tmp pull") 'This is a temp draft sheet to pull the data that you'll need to create
For Each Fch In Ws1.Range("I2", Ws1.Range("I2").End(xlDown))
Ws2.Cells.Clear
Ws2.Range("G1:G999").FormulaR1C1 = "=IF('" & Fld & "[" & Fch.Value & "]resumen'!RC<>"""",'" & Fld & "[" & Fch.Value & "]resumen'!RC,"""")"
Ws2.Range("G1:G999").Value2 = Ws2.Range("G1:G999").Value2
MsgBox Ws2.Range("G9999").End(xlUp).Value
Next Fch
Application.ScreenUpdating = True
End Sub
This leaves a formula in column G that will track the last text, number or date in column G of the resumen worksheet within the closed external workbooks.
Sub xlsxLastG()
Dim i As Long, f As String
With Worksheets("archivos_en_outputs")
For i = 2 To .Cells(.Rows.Count, "I").End(xlUp).Row
'conform C:\Users\public\AppData\Documents\test.xlsb
' to 'C:\Users\public\AppData\Documents\[test.xlsb]resumen'!G:G
f = .Cells(i, "I").Value
f = Left(f, InStrRev(f, Chr(92))) & Chr(91) & Right(f, Len(f) - InStrRev(f, Chr(92)))
f = Chr(39) & f & Chr(93) & "resumen'!G:G"
.Cells(i, "G").Formula = _
"=index(" & f & ", max(iferror(match(1e99, " & f & "), 0), iferror(match(""zzz"", " & f & "), 0)))"
Next i
End With
End Sub
#N/A errors would typically mean column G was blank; #REF! errors would indicate not existing workbook or no resumen worksheet within the referenced workbook.
I have some vArrays which are not clearing out. The purspose of the macro is to work on a raw data tab which has 30+ tabs, each tab holding information for a specific office, 001-New York, etc. The macro is supposed to select x number of tabs (based on a reference file), copy them and save them into a new workbook. The problem is that instead of copying and saving from the raw data file it save the reference file instead. A For...Next loop is used to determine which tabs/offices to select & copy from the raw data file. The varrays are inside the loop and contain the names of the offices. When the code encounters the vArray the varray values are not clearing out when the loop circles back around.
Example:
'For 1' reference a cell with value of "8" so it populates 8 different vArray values (offices in this case). 'For 2' has a reference number of 5 and is supposed to populate 5 vArray values. It does this correctly as I can see the 5 new values in the locals window under vArray (1) thru vArray (5), however, vArray 6 thru 8 are showing values of the previous loop instead of 'Empty'. The vArray values are not clearing out when the macro loops.
sMasterListWBName is the reference file which tells the macro which tabs to copy from the raw data file and where to move the newly created workbook. The sub is also copying, saving, and distributing the reference file instead of the raw data file for some iterations of the loop (secondary issue--I will try to refrain from splitting the thread topic).
Thanks in advance to anyone who tries to answer this question.
Option Explicit
Dim iYear As Integer, iMonth As Integer, iVer As Integer, icount As Integer, iCount2 As Integer
Dim iLetter As String, iReport As String
Dim sMonth As String, sDate As String, sVer As String, sAnswer As String
Dim sFolderName As String, sManagerInitials As String
Dim iManagerNumber As Integer, iManagerStart As Integer, iTabNumber As Integer, iTabStart As Integer
Dim sMasterListWBName As String, sConsolidatedWBName As String, sExists As String
Dim oSheet As Object, oDistList As Object
Dim vArray(300) As Variant
Dim wbDistList As Workbook
Dim wsAgentListSheet As Worksheet, wsMain As Worksheet
Dim rCell As Range, rCell2 As Range, rCellTotal As Range
Public sFINorAgent As String
Sub Agent_Distribute()
On Error Resume Next
iYear = frm_fin_rep_main_distribute.txt_year
iMonth = frm_fin_rep_main_distribute.txt_month
iVer = frm_fin_rep_main_distribute.txt_version
sMonth = Right("0" & iMonth, 2)
sDate = iYear & "." & sMonth
sVer = "V" & iVer
sAnswer = MsgBox("Is the following information correct?" & vbNewLine & vbNewLine & _
"Report - " & frm_fin_rep_main.sLetter & vbNewLine & _
"Year - " & iYear & vbNewLine & _
"Month - " & sMonth & vbNewLine & _
"Name - " & frm_fin_rep_main.sReport & vbNewLine & _
"Version - " & sVer, vbYesNo + vbInformation, "Please verify...")
If sAnswer <> vbYes Then
Exit Sub
End If
Unload frm_fin_rep_main_distribute
frm_agent.Hide
Form_Progress
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
sConsolidatedWBName = ActiveWorkbook.Name
sMasterListWBName = "Dist Master List Final.xls"
If Not IsFileOpen(sMasterListWBName) Then
Workbooks.Open FileName:= _
"W:\Addins\01 GL - Distribution\" & sMasterListWBName, Password:="password"
Workbooks(sConsolidatedWBName).Activate
End If
Set oDistList = Workbooks(sMasterListWBName).Worksheets("Agent")
With oDistList
iManagerNumber = .Range("ManNumber2") 'range value = 66
For iManagerStart = 2 To iManagerNumber '2 to 66
If .Range("A" & iManagerStart) = "x" Then
iTabNumber = .Range("E" & iManagerStart) 'E2 to E66
sFolderName = .Range("F" & iManagerStart) 'F2 to F66
sManagerInitials = .Range("G" & iManagerStart) 'G2 to G66
For iTabStart = 1 To iTabNumber
vArray(iTabStart) = .Range("G" & iManagerStart).Offset(0, iTabStart)
Next iTabStart
If iTabNumber = 1 Then
Sheets(vArray(1)).Select
Else
Sheets(vArray(1)).Select
For iTabStart = 2 To iTabNumber
Sheets(vArray(iTabStart)).Select False
Next iTabStart
End If
ActiveWindow.SelectedSheets.Copy
' *** the following code is optional, remove preceding apostrophes from the following four lines to enable password protection ***
'For Each oSheet In ActiveWorkbook.Sheets
'oSheet.Protect "password"
'oSheet.EnableSelection = xlNoSelection
'Next
ActiveWorkbook.SaveAs FileName:= _
"W:\Financials\" & iYear & "\" & sDate & "\Report to Distribute Electronically\Department Reports\" _
& sFolderName & "\Current Year Financials" & "\" & "Y" & ") " & iYear & "-" & sMonth & " Agent Report Card " & sVer & " - " & sManagerInitials & ".xls"
ActiveWorkbook.Close
End If
iPercent = iManagerStart / iManagerNumber * 95
Task_Progress (iPercent)
Next iManagerStart
End With
Workbooks(sMasterListWBName).Close False
Task_Progress (100)
Unload frm_progress
Set oDistList = Nothing
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Message_Done
frm_agent.Show (vbModeless)
End Sub
I fixed it. I just added "Workbooks(sWbName).activate" at the end of the loop to make sure the focus is back on the raw data file. Now all files are saving in the correct format and location. Case closed unless someone has anything else to add. Maybe someone knows the reason the macro was losing sight of its active sheet (saving reference file instead of raw data file). Thank you.
The below Query is running successfully for single row, I want to repeat the same until 'A' row is empty.Basically, i am copying from A2 and executing that, Results will be loaded into B2.Then Creating one text file store the 'Query n results' and creating a hyperlink.
Kindly help me create a loop and do this until 'A' Columns is empty
This is my Query:
'First Query
Set Sql = Sheet1.Range("A2")
Set Rec_set = cn.Execute(Sql) 'Issue SQL statement
While Not Rec_set.EOF
Sheet1.Range("B2").CopyFromRecordset Rec_set
Wend
Rec_set.Close 'Close the recordset
'Write into TEXT file
Set Fileout = fso.CreateTextFile("C:\Text\Row2.txt", True, True)
Fileout.Write Sheet1.Range("A2")
Fileout.Write vbNewLine
Fileout.Write vbNewLine
Fileout.Write "COUNT"
Fileout.Write vbNewLine
Fileout.Write "*****"
Fileout.Write vbNewLine
Fileout.Write Sheet1.Range("B2")
Fileout.Close
With Worksheets("Sheet1")
.Hyperlinks.Add Anchor:=.Range("C2").End(xlUp).Offset(1, 0), _
Address:="https:XXXXXXXXXXXXX/Screenshots/Text/Row2.txt", _
ScreenTip:="Hyperlink", _
TextToDisplay:="Row2"
End With
Thanks,
I believe the following should work as expected:
Sub foo()
LastRow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
'First Query
For i = 2 To LastRow
Set Sql = Sheet1.Range("A" & i)
Set Rec_set = cn.Execute(Sql) 'Issue SQL statement
While Not Rec_set.EOF
Sheet1.Range("B" & i).CopyFromRecordset Rec_set
Wend
Rec_set.Close 'Close the recordset
NewPath = "C:\Text\Row" & i & ".txt"
'Write into TEXT file
Set Fileout = fso.CreateTextFile(NewPath, True, True)
Fileout.Write Sheet1.Range("A" & i)
Fileout.Write vbNewLine
Fileout.Write vbNewLine
Fileout.Write "COUNT"
Fileout.Write vbNewLine
Fileout.Write "*****"
Fileout.Write vbNewLine
Fileout.Write Sheet1.Range("B" & i)
Fileout.Close
With Worksheets("Sheet1")
.Hyperlinks.Add Anchor:=.Range("C" & i).End(xlUp).Offset(1, 0), _
Address:="https:XXXXXXXXXXXXXXXXXXXXXX/Screenshots/Text/Row" & i & ".txt", _
ScreenTip:="Hyperlink", _
TextToDisplay:="Row" & i
End With
Next i
End Sub
You need a loop from the first row of A to the last row of A. Thus, on an empty worksheet, write a few words in column A and try this part separately. Then adjust it to your code:
Option Explicit
Public Sub TestMe()
Dim lastRowA As Long
Dim cnt As Long
lastRowA = lastRow
For cnt = 1 To lastRowA
Debug.Print Cells(cnt, 1)
Next cnt
End Sub
Function lastRow(Optional wsName As String, Optional columnToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
lastRow = ws.Cells(ws.Rows.Count, columnToCheck).End(xlUp).Row
End Function
The lastRow function has 2 optional parameters - thus, if you need the last row of column B of Sheets2 then it would look like this -> lastRow("Sheet1",2).
I'm trying to copy a worksheet ("ReceivingRecords") from the workbook ("InventoryControlSystemV1.1") and paste it in a new workbook ("RecordBook"). I have created a temporary workbook named "Temp.xls" which allows me to use the SaveCopyAs method to create my new workbook "RecordBook".
When I run the procedure, "RecordBook" is created as intended but with only one entry (The text 'InventoryControlSystemV1.1.xls') in cell A1.
The worksheet that I want to copy is then pasted into a new, unnamed, workbook.
I can't figure out where or why this new workbook is being created.
Here is the code for this procedure:
Sub WriteReceivingToRecords()
Dim UsedRng As Range
Dim LastCol As Long
Dim BeginDate, EndDate
Dim NameString
Dim FormatBeginDate, FormatEndDate
Dim BackupQuest As Integer
Dim BackupMsg As String
'Confirmation dialog box to avoid mistakes
BackupMsg = "This will create a new workbook for the period" & vbNewLine
BackupMsg = BackupMsg & " since the last backup was made, and will clear" & vbNewLine
BackupMsg = BackupMsg & " the receiving records in this workbook." & vbNewLine & vbNewLine
BackupMsg = BackupMsg & "Are you sure you want to back up the receiving records?"
BackupQuest = MsgBox(BackupMsg, vbYesNo, "Back-up Records")
If BackupQuest = vbNo Then
Exit Sub
Else
' Find start and end dates of receiving - To use for worksheet title
Workbooks("InventoryControlSystemV1.1.xls").Activate
Worksheets("ReceivingRecords").Activate
Set UsedRng = ActiveSheet.UsedRange
LastCol = UsedRng(UsedRng.Cells.Count).Column
Do While Cells(2, LastCol) = ""
LastCol = LastCol - 1
Loop
EndDate = Cells(2, LastCol).Text
BeginDate = Cells(2, 2).Text
FormatBeginDate = Format(BeginDate, "d mmmm yy")
FormatEndDate = Format(EndDate, "d mmmm yy")
NameString = "M-Props Receiving Records " & FormatBeginDate & " To " _
& FormatEndDate & ".xls"
Workbooks("InventoryControlSystemV1.1.xls").Sheets("ReceivingRecords").Copy
Workbooks.Open Filename:="Temp.xls"
Workbooks("Temp.xls").Activate
Workbooks("Temp.xls").Worksheets("Sheet1").Paste _
Destination:=Workbooks("Temp.xls").Worksheets("Sheet1").Range("A1")
Workbooks("Temp.xls").SaveCopyAs NameString & ".xls"
Workbooks("Temp.xls").Close False
End If
End Sub
Replace
Workbooks("InventoryControlSystemV1.1.xls").Sheets("ReceivingRecords").Copy
with
Workbooks("InventoryControlSystemV1.1.xls").Sheets("ReceivingRecords").Cells.Copy
That should do it.