I have been working on a workbook for some reporting functions.
I have just been getting back into VB and a bit rusty - in front of me also sits a 1000+ page book and have been all over sites like this. It seems that i can get close - however end up just a bit off.
Every week I have new data coming in, that I will be using to update some pivot tables and so on. I have 5 areas where data will be imported and currently have the import functioning, however I run into issues with two areas: I can't seem to have it create a table of the data that was just imported & I have no error checking. I need the tables named so i can use the date throughout the worksheet.
Any guidance would be great for the following:
How can I simply clear out the current table at A2 and import the new data not to have to rename the table and the headers? (my imported data comes in as "First Name" not First_Name" so would be nice to just keep it in this format.
How do I add error checking on this to say if someone runs it and closes the window that it will not clear the worksheet and launch a debugger?
Here is what i have working (I have tried many things but back to this)
Sub ImportMaster()
' this is the master list of all NA accounts for .....
' NA_ACCOUNTS_LIST Worksheet
Dim ws As Worksheet, strFile As String Set ws = ActiveWorkbook.Sheets("NA_Accounts_List") ws.UsedRange.Clear strFile = Application.GetOpenFilename("Text Files (*.csv),*.csv", , "Please selec text file...") With ws.QueryTables.Add(Connection:="TEXT;" & strFile, _ Destination:=ws.Range("A2"))
.Name = "ProgramData"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 2
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False End With ' ws.Name = "testing"
' updates the date Range("C12").ClearContents Range("C12") = Format(Date, "mm-dd-yyyy")
' This will focus this worksheet after upate Sheets("NA_Accounts_List").Visible = xlSheetVisible Sheets("NA_Accounts_List").Select
MsgBox "Imported data successfully!"
end sub
let me see if i understood, what you want is clear cell A2 from the current table that you are working? and insert a new data at the same cell?
You have lucky, i guess its should solve.
Microsoft.Office.Interop.Excel.Application ex = new Microsoft.Office.Interop.Excel.Application();
ex.Visible = true;
Microsoft.Office.Interop.Excel.Workbook wk = ex.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wk.Worksheets[1]; // set the first worksheet
DataTable dtb = mysql.mysql_data_adapter(); // the data that are coming from mysql
DataRow row;
for (int i = 0; i < dtb.Columns.Count; i++) // add header
{
Microsoft.Office.Interop.Excel.Range rg = (ws.Cells[1, i + 1] as Microsoft.Office.Interop.Excel.Range); // excel start in 1
rg.Value2 = dtb.Columns[i].ColumnName.ToString();
}
for (int i = 2; i < dtb.Rows.Count + 2; i++) // add data without change header, and this for run the row
{
row = dtb.Rows[i - 2]; // where to start at correct row, dont oforget, start in 2 because 1 are the header
for (int i2 = 1; i2 < dtb.Columns.Count + 1; i2++) // where run the collumns
{
try
{
Microsoft.Office.Interop.Excel.Range rg = (ws.Cells[i, i2] as Microsoft.Office.Interop.Excel.Range);
rg.Value2 = row[i2 - 1].ToString();
}
catch
{
}
}
}
Related
I'm trying to upload a CSV file with breaklines inside quotes (data.csv) but instead of putting all the text inside the quote in one cell, it still considers it as a new row.
When I open the CSV directly, everything works fine but when I run it through VBA, everything is getting messed up.
data.csv sample
cases,"variant:
option1: 0333102
option2: 1133202
option3: 4234442"
make-shift,"variant:
option1: shift iron
option2: workload
option3: network map
option4: lesson map"
Import_CSV Function
Function import_CSV(location As String, row As Integer, col As String) As Variant
Dim ws As Worksheet, strFile As String
Sheets("data").Visible = True
Sheets("data").UsedRange.ClearContents
Set ws = Sheets("data")
strFile = location
With ws.QueryTables.Add(Connection:="TEXT;" & strFile, Destination:=ws.Range("A1"))
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 850
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
import_CSV = Sheets("data").Range(col & "1:" & Get_C(Last_C(row, "data")) & Last_R(Get_C(Last_C(row, "data")), "data"))
Sheets("data").Visible = False
End Function
Assuming your import_CSV() returns the range in data worksheet with same size as the imported CSV, try below. Don't really need the row integer and col string, so I have omitted it.
Option Explicit
Function ImportCustomCSV(location As String) As Range
Dim oWbCSV As Workbook, oRngCSV As Range, oRngData As Range
ThisWorkbook.Worksheets("data").UsedRange.ClearContents
' Range to start pasting csv data
Set oRngData = ThisWorkbook.Worksheets("data").Range("A1")
' Assumes file availability is already checked
Set oWbCSV = Workbooks.Open(Filename:=location, ReadOnly:=True)
Set oRngCSV = oWbCSV.Worksheets(1).UsedRange
' Copy the CSV range to data worksheet
oRngCSV.Copy oRngData
' Make the data range the same rows and cols as imported csv
Set oRngData = oRngData.Resize(oRngCSV.Rows.Count, oRngCSV.Columns.Count)
' Cleanup
Set oRngCSV = Nothing
oWbCSV.Close SaveChanges:=False
Set oWbCSV = Nothing
' Return the updated data range
Set ImportCustomCSV = oRngData
End Function
When I extract my data from this one software into raw text it separates the values with commas and quotation marks for the majority of the file. Except in certain cases the data has a line break. When I save it as a .csv and open it, the data is cleanly formatted into a proper table.
However, if I attempt the same process with QueryTablesit processes the enter character as a new line.
I have two different approaches in two different subprograms
The first is able to read the number of rows and columns properly, but since it uses the QueryTables method it reads that enter charachter as a new line.
The code for this approach is below:
Private Sub OpenCSVFile()
With ThisWorkbook
Set primeSheet = .Sheets.Add(After:=.Sheets(.Sheets.Count))
primeSheet.Name = "Temp"
End With
Set informationRange = primeSheet.Range("A1")
xAddress = informationRange.Address
With primeSheet.QueryTables.Add("TEXT;" & strPath, primeSheet.Range(xAddress))
.AdjustColumnWidth = False
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = False
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SaveData = False
.RefreshPeriod = 0
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
rowLength = primeSheet.Cells(1, Columns.Count).End(xlToLeft).Column
colLength = primeSheet.Cells(Rows.Count, "A").End(xlUp).Row
End Sub
The other method keeps the formatting intact as to when I regularly open .csv files of my extracted data, but it is unable to read the number of rows and lengths, and returns a value for 1 for each.
Private Sub OpenCSV()
Set primeBook = Workbooks.Open(strPath)
With primeBook
rowLength = Sheet1.Cells(1, Columns.Count).End(xlToLeft).Column
colLength = Sheet1.Cells(Rows.Count, "A").End(xlUp).Row
End With
Set informationRange = Sheet1.Range("A1", Sheet1.Cells(colLength, rowLength))
End Sub
How would you recommend I address my issue and read the contents of the csv file while ensuring no weird line breaks.
Would this work?
Private Sub OpenCSV()
Set primeBook = Workbooks.Open(strPath)
With primeBook.Sheet1
rowLength = .usedrange.rows.count
colLength = .usedrange.columns.count
End With
Set informationRange = Sheet1.Range("A1", Sheet1.Cells(colLength, rowLength))
End Sub
Hey so i found a specific query to import a file into excel from a specific row and delete the following datga each time you open it again. but is it also pssible to stop adding rows at a specific line? and is it possible to leave some rows out if there for example is a specific word in that line?
Sub Sample()
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Users\sample.txt", Destination:=Range("$A$1") _
)
.Name = "Sample"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
You can do it, but not with a Querytable.
Try this code:
Private Sub Open_Click()
Dim fn As Variant, myLine As Long, txt As String, x As Variant, ouput As String
Dim i As Integer, j As Integer: j = 1
Dim sht As Worksheet
Set sht = Worksheets("Sheet1") 'Modify Sheet Name
fn = Application.GetOpenFilename("Text Files (*.txt),*.txt", , _
"Open File")
If fn = False Then Exit Sub
txt = CreateObject("Scripting.FileSystemObject").OpenTextFile(fn).ReadAll
x = Split(txt, vbNewLine)
For i = 0 To UBound(x)
If x(i) <> "SomeCriteria" Then 'Check for some criteria
sht.Cells(j, 1).Value = x(i)
j = j + 1
End If
Next i
End Sub
So what it does basically, it opens a user selected txt file and stores it in the variable txt. Do seperate the rows you can use the split-function. Now each line is stored in an array x. You could go trough the array/each line and take out the ones you want. To check if a specific word is in a line, use the InStr-function.
I have 100 .txt files. Each .txt is connected to a different sheet in the workbook. I would like to name the sheet based on the name of .txt file connected in that sheet.
Here are some code.
Unfortunately they do not work as I got the error: "name already taken"
Sub MultipleTextFilesIntoExcelSheets()
Dim i As Integer 'a counter to loop through the files in the folder
Dim fname As String, FullName As String 'fname is the name of the file, and FullName is the name of its path
Dim ws As Worksheet 'a workbook object for the workbook where the current macro is running
''' Delete existing data connections
''''''''''''''''''''''''''''''''''''
Do While ActiveWorkbook.Connections.Count > 0
ActiveWorkbook.Connections.Item(ActiveWorkbook.Connections.Count).Delete
Loop
''' Rename raw data sheets to default string
''''''''''''''''''''''''''''''''''''''''''''
i = 1
For Each ws In Worksheets
If ws.Name Like "Test1" Or ws.Name Like "Test2*" = True Then
'Do Nothing
ElseIf ws.Name Like "Test1" Or ws.Name Like "Test2*" = False Then
ws.Name = "Sheet" & i
i = i + 1 'get ready for the next iteration
End If
Next ws
''' Import .txt files
'''''''''''''''''''''
i = 0
'get the name of the first text file
fname = Dir("C:\Sample\Test\*txt")
'loop through the text files to put them onto separate sheets in the Excel book
While (Len(fname) > 0)
'get the full path of the text file
FullName = "C:\Sample\Test\" & fname
i = i + 1 'get ready for the next iteration
Set ws = ThisWorkbook.Sheets("Sheet" & i) 'the current sheet
With ws.QueryTables.Add(Connection:="TEXT;" & FullName, Destination:=ws.Range("A1"))
.Name = fname
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlOverwriteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True 'we are using a tab-delimited file
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileOtherDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
fname = Dir
End With
Wend
''' Rename sheets to new string
'''''''''''''''''''''''''''''''
For Each ws In Worksheets
If ws.Name Like "Test1" Or ws.Name Like "Test2*" = True Then
'Do Nothing
ElseIf (ws.Name Like "Test1" Or ws.Name Like "Test2*" = False) Then
ws.Name = Left(fname, (Len(fname) - 4))
End If
Next ws
End Sub
Thank you in advance,
Fede
You use Dir once to put an initial value into fname but then never change this initial value. In the second pass through the loop you are still using the same fname, hence Excel complains that you are using a name that is already taken.
It might work to insert the line fname = Dir right before Next ws. This would seem to be what you want, though I am uncomfortable with the overall logic of your code since it isn't clear how it guarantees that the right name goes with the right sheet. It might make more sense to write a sub that starts with an initially empty workbook and iterates through the folder importing the data and naming the sheets in one pass.
Also -- I think the logic of your ElseIf is murky. For one thing -- why not a simple Else?
If I understand correctly you will need to move the renaming of the sheets into your while loop prior to updating fname. (Update the sheet when you already know which sheet needs to be renamed)
While my code works for 10 loop iterations, it crashes for home = 30 or more. Can someone please provide me with a clue? Even weirder this code used to work fine... and is not working anymore.
Here's the code:
Sub datascrap_clean()
'
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Dim home As Integer
Dim output_rows As Integer
Dim output_columns As Integer
Dim date_columns As Integer
'Output rows and columns starting values
output_rows = 3
output_columns = 3
date_columns = 8
For home = 3 To 33
With ActiveSheet.QueryTables.Add(Connection:= _
"URL;http://www.cqc.org.uk/directory/" & Sheets("Output").Cells(home, 1), Destination:=Range("$A$1") _
)
'.CommandType = 0
.Name = "Homes"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlEntirePage
.WebFormatting = xlWebFormattingNone
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
For x = 20 To 250
Select Case Left(Cells(x, 1), 7)
'Is it a score?
Case Is = "Overall"
Sheets("Output").Cells(output_rows, output_columns).Value = Cells(x, 1)
output_columns = output_columns + 1
'Is it a date?
'Case Is = "Carried"
' Sheets("Output").Cells(output_rows, output_columns).Value = Cells(x, 1)
'date_columns = date_columns + 1
Case Else
End Select
Sheets(2).Select
Next x
'Clean sheet
ActiveSheet.Cells.Delete
'Reset column count
output_columns = 3
date_columns = 8
output_rows = output_rows + 1
Next home
MsgBox ("Done!")
End Sub
I had the same problem with creating QueryTable objects within a loop and having Excel hang at seemingly random times (usually after creating about 15 QueryTable objects). I noticed that the problem did not happen when I was in the VBE debugging and running with breakpoints inserted. So, in addition to deleting QueryTable objects after using them as suggested in a previous answer, I inserted a short delay at the start of my loop:
Application.Wait(Now + TimeValue("0:00:02"))
Was able to successfully run a case with ~300 QueryTable objects created with no hanging. Yes, a kludge, but it least provides a work around. Without the delay, I still got Excel to hang even after deleting the QueryTable objects.