I have many documents in CSV format(about 100 different .csv files). I want to merge all of them into one .xls document. I want each CSV document to represent a worksheet in my new xls document. So my final result should be one xls workbook with 100 different worksheets which were originally .csv documents.
I'd use a scripting language such as vbs. It plays well with Excel and other MS Applications, and you can run it from either command line or double clicking on the file.
You need to add values for those two arguments or
If you do command line you can pass the srccsvfile and tgtxlsfile parameters like:
cscript nameoffile.vbs test.csv test.xls
Here is some sample code. Save as nameoffile.vbs:
srccsvfile = Wscript.Arguments(0)
tgtxlsfile = Wscript.Arguments(1)
'Create Spreadsheet
'Look for an existing Excel instance.
On Error Resume Next ' Turn on the error handling flag
Set objExcel = GetObject(,"Excel.Application")
'If not found, create a new instance.
If Err.Number = 429 Then '> 0
Set objExcel = CreateObject("Excel.Application")
End If
objExcel.Visible = false
objExcel.displayalerts=false
'Import CSV into Spreadsheet
Set objWorkbook = objExcel.Workbooks.open(srccsvfile)
Set objWorksheet1 = objWorkbook.Worksheets(1)
'Adjust width of columns
Set objRange = objWorksheet1.UsedRange
objRange.EntireColumn.Autofit()
'This code could be used to AutoFit a select number of columns
'For intColumns = 1 To 17
' objExcel.Columns(intColumns).AutoFit()
'Next
'Make Headings Bold
objExcel.Rows(1).Font.Bold = TRUE
'Freeze header row
With objExcel.ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
objExcel.ActiveWindow.FreezePanes = True
'Add Data Filters to Heading Row
objExcel.Rows(1).AutoFilter
'set header row gray
objExcel.Rows(1).Interior.ColorIndex = 15
'-0.249977111117893
'Save Spreadsheet, 51 = Excel 2007-2010
objWorksheet1.SaveAs tgtxlsfile, 51
'Release Lock on Spreadsheet
objExcel.Quit()
Set objWorksheet1 = Nothing
Set objWorkbook = Nothing
Set ObjExcel = Nothing
Related
The first routine grabs the filename string as the user locates a file which was exported from Quickbooks
The second routine writes that name into the name manager as a string under the name
"PathToEmployeeWithholding"
The third routine attempts to open the file using the name stored in the name manager
I have verified in the name manager that the name and correct path string is there, but I have not been successful in using that name to retrieve the file for reading.
The current code returns a 1004 error, but debug.print does give the correct path, pasting the string in the windows run box opens the spreadsheet, and so does a static statement with the path.
Thanks in advance for your help
lang-VB
'HouseKeepingCODE Module
Sub GetPath()
'This sub gets the path to a File defined by the user within the routine
'It then calls another sub that applies that path to a name in the worksheet.
' Before calling this routine, The name should first be searched for, and then verified, then opportunity given to change the name.
Dim MyPath As String 'String to hold the path to an excel spreadsheet exported from quickbooks
Dim NameToChange As String 'String that holds the name manager name to store the path under
Dim NameComment As String 'Comment to identify the name in the name manager
NameToChange = "PathToEmployeeWithholding"
NameComment = "This Name contains the Path to the 'Employee Withholding' worksheet exported from quickbooks using VBA"
With Application.FileDialog(msoFileDialogFilePicker)
If .Show <> 0 Then
MyPath = .SelectedItems(1)
End If
End With
'Debug.Print PathToWithholding
'This routine should be modified
'It should simply get a path to a file,
'And return that path to the calling subroutine
'The calling subroutine should then add comment and call the changevalueofname subroutine
Call ChangeValueOfName(NameToChange, MyPath, NameComment) 'this routine stores the retrieved text string in the name manager
End Sub
Sub ChangeValueOfName(NameToChange As String, NewNameValue As String, Comment As String)
'
' ChangeValueOfNameMagagerName Macro
' Changes the Value of a defined name in the Name Manager
'This should be used to change the name.
'
'Once the file is selected data needs to be imported to an array, and the
'Employee name values need to be checked against the worksheets in the workbook and against the recap sheet
'If changes are needed, it needs to write them into the workbook, including changing recap sheet and adding
'worksheets for any new employees
'
'
'
'
With ActiveWorkbook.Names(NameToChange)
.Name = NameToChange
.RefersTo = NewNameValue
.Comment = Comment
End With
End Sub
'****problem subroutine below***
Sub UpdateEmployeewithholding()
'This sub will clean employee withholding as it is exported from quickbooks and then read the file into this workbook
'The path is already stored in the names manager
'This routine needs to integrate changevalueofname and getpath. They should update before executing the balance of this routine
Dim MyWorkBook As Workbook
Dim MyPath As Variant 'Contains path to employee withholding spreadsheet as exported from quickbooks. This sheet is to be modified for reading, but not saved
Dim MyRange As Range 'Contains a defined range after setting it so
Dim whichrow As Variant 'Marks the starting point for routines that find and delete blanks as well as those that define range values and scan them into an array
Dim Direction As Variant 'Defines whether we are progressing over "Rows" or "Columns"
Dim ArrayWidth As Range 'Holds the top row addresses of the array
Dim ArrayHeight As Range 'Holds the left column addresses of the array
Dim MyArray As Variant 'Holds the array to transfer to this spreadsheet
Dim Width As Long 'Holds the array width to prevent loosing it when the original spreadsheet closes
Dim Height As Long 'Holds the array height to prevent loosing it when the original spreadsheet closes
whichrow = 1 'We are starting in cell A! or R1C1
Direction = "Rows"
'******************************************************************************************************
'***INSERT Code that will read the string value stored in the name manager Name "PathToEmployeeWithholding" into the variable "MyPath"
' and eliminate the hard coded path from the routine
' STILL MISSING
'*****************************************************************************************************
'Setting MyPath to the fixed path to employee withholding until we can get the routine to 'open the workbook from a varialbe
'stored in the name manager
MyPath = ThisWorkbook.Names("PathToEmployeeWithholding")
'ActiveWorkbook.Names (PathToEmployeeWithholding)
Debug.Print MyPath 'This works
Set MyWorkBook = Workbooks.Open(MyPath) '***Problem line returns 1004 stored-path could
'not be found
Debug.Print ActiveWorkbook.Name
'**** The immediate statement below worked ***
debug.Print thisworkbook.Names("PathToEmployeeWithholding")="D:\redacted\Employee Withholding .xlsx"
'***Code below to extract data from workbook opened above
The problem was in the fact that pulling the name back from name manager always added an = sign plus open and close quotes for delimiters. .eg
="string\text"
The solution was to strip the delimiters using the mid function
Sub UpdateEmployeewithholding()
'This sub will clean employee withholding as it is exported from quickbooks and then read the file into this workbook
'The path is already stored in the names manager
'This routine needs to integrate changevalueofname and getpath. They should update before executing the balance of this routine
Dim MyWorkBook As Workbook
Dim MyPath As String 'Contains path to employee withholding spreadsheet as exported from quickbooks. This sheet is to be modified for reading, but not saved
Dim MyRange As Range 'Contains a defined range after setting it so
Dim whichrow As Variant 'Marks the starting point for routines that find and delete blanks as well as those that define range values and scan them into an array
Dim Direction As Variant 'Defines whether we are progressing over "Rows" or "Columns"
Dim ArrayWidth As Range 'Holds the top row addresses of the array
Dim ArrayHeight As Range 'Holds the left column addresses of the array
Dim MyArray As Variant 'Holds the array to transfer to this spreadsheet
Dim Width As Long 'Holds the array width to prevent loosing it when the original spreadsheet closes
Dim Height As Long 'Holds the array height to prevent loosing it when the original spreadsheet closes
Dim StrLength As Long
whichrow = 1 'We are starting in cell A! or R1C1
Direction = "Rows"
MyPath = ThisWorkbook.Names("PathToEmployeeWithholding") 'get string from name manager
Debug.Print MyPath 'As stored in name manager the name always returns and = sign plus open and close quotes
StrLength = Len(MyPath) 'In order to get the workbook to open programatically these must be stripped
MyPath = Mid(MyPath, 3, StrLength - 3) 'The mid statement strips these delimiters off, leaving just the text
Debug.Print MyPath
Set MyWorkBook = Workbooks.Open(MyPath)
Debug.Print ActiveWorkbook.Name
'Stuff below gets data from opened workbook
I really need your help with this.
I have created an invoice template in Google Docs with databases flowed from Google sheets.
The problem is:
In the template (Google Docs), I only put a specific items line (eg 3 lines).
When the data is changed, such as the number of items lines are changing, how it's automatically gone through Google Docs if there are more than 3 items lines
Many thanks for your help.
Below is my script to get data from G-sheets to G-Docs template.
function Invoice() {
let copyFile = DriveApp.getFileById('id URL').makeCopy(),
copyID = copyFile.getId(),
copyDoc = DocumentApp.openById(copyID),
copyBody = copyDoc.getBody()
let activeSheet = SpreadsheetApp.getActiveSheet(),
numOfCol = activeSheet.getLastColumn(),
activeRowIndex = activeSheet.getActiveRange().getRowIndex(),
activeRow = activeSheet.getRange(activeRowIndex, 1, 1, numOfCol).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numOfCol).getValues(),
columnIndex = 0
for (; columnIndex < headerRow[0].length; columnIndex++){
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%', activeRow[0][columnIndex])
}
copyDoc.saveAndClose()
Here is screenshot of the files.
Data in G-sheet with the additional item (Item 4)
G-Docs template with specific 3 rows for 3 items lines
When I have 4 items, I must manually amend the G-Docs template. Is there any way to get its automatically.
#Duc I don't think it's possible to pass the new header as placeholder in the GDoc, it sounds like an endless loop.
Unless you pass it as List_ITEM, but I am pretty sure you will lose formatting.
I am trying to implement a Matrix Grid Control in my project. Trying to follow the instructions:
http://wiki.genexus.com/commwiki/servlet/hwiki?HowTo%3A+Using+Matrix+Grid+Control+for+Smart+Devices
I have already created an XAxis (rows), YAxis (columns) and data SDTs, set the properties and fill the data, but no matter what, I always end up with a "Application needs to close" message (Android).
Maybe I'm not doing things right, do you know where I can find a project source to use as a reference?
Thanks
I found a way of solving the error.
Columns and Headers are still being filled by a SDT (loaded in Start Event).
Replaced the data SDT by a layout var (&valueVar) inside the Matrix Control, being loaded in Load Event.
Event Grid1.Load
&xfrom = 1
&xto = 1
&yfrom = 1
&yto = 1
&valueVar = 'Value 1'
LOAD
&xfrom = 2
&xto = 2
&yfrom = 2
&yto = 2
&valueVar = 'Value 2'
LOAD
Endevent
I am trying to iterate through an unstrucutred csv file (it has no specific headings). The file is generated by an instrument. I would need to select specific rows that have specific column values and create another file. Below is the example of the file layout
,success, (row1)
1,2,protocol (row2)
78,f14,34(row3)
,67,34(row4)
,f14,34(row5)
3,f14,56,56(row6)
I need to select all rows with 'fi4' value. Below is the code
import csv
import sys
reader = csv.reader(open('c:/test_file.csv', newline=''), delimiter=',', quotechar='|')
for row in reader:
print(','.join(row))
I am unable to go beyond this point.
You're almost there:
for row in reader:
if row[1] == 'f14':
print(','.join(row))
You just need to check and see whether the row is one you're interested in or not by checking the value of the column and see if it's what you're looking for. That could be done with a simpleif row[1] == 'f14'conditional statement. However that would fail on any blank lines -- which it looks like your input file may have -- so you'd need to preface that check with another to make sure the row had at least that many columns in it.
To create another csv file with just those rows in it, all you'd need to write each row that passed all the checks to another file opened for output -- instead of, or in addition to, printing the row out. Here's a very concise way of just writing the rows to another file.
(Note: I'm not sure why you had thequotechar='|'in your code on thecsv.reader()call because there aren't any quote characters in the input file shown, so I left it out in the code below -- you might need to add it back if indeed that's what it would be if there were any.)
import csv
with open('test_file.csv', newline='') as infile, \
open('test_file_out.csv', 'w', newline='') as outfile:
csv.writer(outfile).writerows(row for row in csv.reader(infile)
if len(row) >= 2 and row[1] == 'f14')
Contents of'test_file_out.csv'file afterwards:
78,f14,34(row3)
,f14,34(row5)
3,f14,56,56(row6)
I have a simple 4-column Excel spreadsheet that matches universities to their ID codes for lookup purposes. The file is pretty big (300k).
I need to come up with a way to turn this data into a populated table in my Rails app. The catch is that this is a document that is updated now and then, so it can't just be a one-time solution. Ideally, it would be some sort of ruby script that would read the file and create the entries automatically so that when we get emailed a new version, we can just update it automatically. I'm on Heroku if that matters at all.
How can I accomplish something like this?
If you can, save the spreadsheet as CSV, there's much better gems for parsing CSV files than for parsing excel spreadsheets. I found an effective way of handling this kind of problem is to make a rake task that reads the CSV file and creates all the records as appropriate.
So for example, here's how to read all the lines from a file using the old, but still effective FasterCSV gem
data = FasterCSV.read('lib/tasks/data.csv')
columns = data.remove(0)
unique_column_index = -1#The index of a column that's always unique per row in the spreadsheet
data.each do | row |
r = Record.find_or_initialize_by_unique_column(row[unique_column_index])
columns.each_with_index do | index, column_name |
r[column_name] = row[index]
end
r.save! rescue => e Rails.logger.error("Failed to save #{r.inspect}")
end
It does kinda rely on you having a unique column in the original spreadsheet to go off though.
If you put that into a rake task, you can then wire it into you're Capistrano deploy script, so it'll be run every time you deploy. the find_or_initialize should ensure you shouldn't get duplicate records.
Parsing newish Excel files isn't too much trouble using Hpricot. This will give you a two-dimensional array:
require 'hpricot'
doc = open("data.xlsx") { |f| Hpricot(f) }
rows = doc.search('row')
rows = rows[1..rows.length] # Skips the header row
rows = rows.map do |row|
columns = []
row.search('cell').each do |cell|
# Excel stores cell indexes rather than blank cells
next_index = (cell.attributes['ss:Index']) ? (cell.attributes['ss:Index'].to_i - 1) : columns.length
columns[next_index] = cell.search('data').inner_html
end
columns
end