read xls file and re-export without lose initial data - ruby

I m using “spreadsheet”ruby gem to generate xls files.
I have already an xls file “MyFile.xls” which contains many sheets: sh_01, sh_02, sh_03 …
I want to read the name of the last sheet (sh_last_number) and add a new sheet called “sh_last_number+1” to this file (MyFile.xls) and write some data on it.
In other words, I have to open it (read data) and write on it at the same time.
If this idea can’t be realized with Spreadsheet, is their another gem more efficient?
Thanks in advance.

You can definitely do this with the spreadsheet gem. Since you are working with excel files, you may need to require the excel component of the gem if you are using an older version:
require 'spreadsheet' # You may need to require 'spreadsheet/excel'
Then working with and writing pages is simple. To open the workbook (xls file with multiple pages) you do something like:
#workbook = Spreadsheet.open("MyFile.xls")
And then to add a sheet to the workbook you've opened, you simply:
new_sheet = "sh_#{#workbook.worksheets.size + 1}"
#worksheet = #workbook.create_worksheet(:name => new_sheet)
Hope this helps.
Cheers,
Sean

Related

ruby excel - write data to existing xls

I have tried different gems in ruby and also searched a lot but Ruby doesnt seem to have a solution to write to existing excel file.
my excel file 'services.xls' has 3 columns
1st column name is 'inputxlm'
2nd column name is 'methodtoexecute'
3rd column name is 'output'
i have internal logic which takes the inputxlm, process it using the method and generates output
How do i write back the output to output column in 'services.xls' ?
Note : I dont want to use win32ole as my organization has some limitation on it
This article is a great source to find out which library suits you best: https://spin.atomicobject.com/2017/03/22/parsing-excel-files-ruby/
My company uses axlsx combined with axlsx_rails to render xls files with Rails rendering machine and axlsx_styler for styling.
Note that in a simple use case like the one you describe, you night not need an excel file like xls, a mere CSV would suffice, and for that, Ruby has CSV

How to add content to a worksheet by referencing its name in ruby using axlsx gem?

I have created a workbook with multiple worksheets using axlsx. I've also given names to each of the worksheets. Now, I want to add content to one of the existing worksheets. Is there any way to reference the worksheet I want to add content to? That would be the easiest way.
I've also read that somewhere that you could use another gem to read the excel file then modify it. Does it have to be one with read/write capabilities like rubyXL or can I use one gem to read and then use axlsx again to write on it?

How to simply pull information from excel to use as a variable ruby

I am trying to pull product ID's, that are in Excel, into ruby to use as a temporary variable. I cannot find a simple solution and am not sure if I should use the spreadsheet gem or axlsx gem. If you guys could help get me started that would be amazing!
One simple solution would be to save the excel document as a csv. Then it would be relatively easy to to open the file with your ruby program, read in the data you need and put that into a variable, for example using the CSV library
CSV.foreach("path/to/file.csv") do |row|
# use row here
end

Iterate through every excel file in one directory, convert individual sheets to CSV files

I'be been trying to write a bit of code that iterates through every excel file in one directory, and convert excel workbooks to individual sheets to CSV files. I'm quite new to both ruby and coding in general, so I've no idea if my solution is the best method. The problem I am having is the Dir.foreach doesn't seem to iterate correctly, instead returning "C:\gernericfolder\." This then causes the next win32ole code block a whole tonne of problems.
This is my code:
require 'rubygems'
require 'iconv'
require 'win32ole'
require 'csv'
require 'roo'
begin
puts("=================================================================================================================================")
inputFolder = ARGV[0]
outputFolder = ARGV[1]
#Check if the file actually exists + UI Feedback
if File.exists?(inputFolder) == false
puts("IGM: DIRECTORY NOT FOUND. Please check your path exists\n")
Process.exit
end
Dir.foreach(inputFolder) { |nextFile|
#Form the file path and open the file
filePath = "#{inputFolder}\\#{nextFile}"
puts("Next file = #{filePath}")
xl = WIN32OLE.new('excel.application')
book = xl.workbooks.open(filePath)
xl.displayalerts = false
end
end
I've been getting one showstopper problem using EXCEL via win32ole with Ruby 1.9.3/WATIR Classic: I get an intermittent Security error - "Watir::Exception::FrameAccessDeniedException IE will not allow access to this frame for security reasons. You can work around this with browser.goto(frame.src)".
The control this often happens with, but not all the time, is a IFRAME JavaScript link under Internet Explorer 10. I found a work-around that eliminates the issue if I assign the page URL to the list of trusted sites. But because I had to uncheck the HTTPS: checkbox to allow HTTP: URLs, it is unacceptable security practices and I got my wrist virtually slapped.
Our architect says it should be consistent if it's really a Security error. He ran tests which convinced him that the issue is not with Security but rather with using EXCEL and some related process: He eliminated EXCEL, which I was using to pass different UserIDs and Passwords to the Watir script. Once he eliminated EXCEL from the picture, the error no longer happened. Here's how he did it: He ran the first iteration of the script over and over in a batch file that clicked on the frame/link in question the same number of times that the EXCEL table was driving it, and the problem no longer happened. Now I have to use EXCEL some other way beside the win32ole, or go to using .CSV files, which I don't really look forward to because I lose track of how many commas I'm counting.
One solution to your problem, however primitive, is to manually copy and paste the EXCEL data into the .CSV tables.
Another possibility is a suggestion from a colleague: Use EXCEL via the "Ruby Gem Spreadsheet". She is using that and has not had any issues, although I'm pretty sure she isn't using IFRAMES with JavaScript hyperlinks on web pages written in .NET C#. Her app is written in JAVA. But I will look into that option.
Dir.foreach iterates through directory entries, not exactly files. That means, it returns such entries as . (this directory) and .. (parent directory) among others. That's what you get: your nextFile is ..
The best way to quickly solve is is probably to switch from Dir.foreach to Dir.glob or Dir[]. That is, replace
Dir.foreach(inputFolder) { |nextFile|
#Form the file path and open the file
filePath = "#{inputFolder}\\#{nextFile}"
puts("Next file = #{filePath}")
with
Dir.glob(inputFolder+'\**') { |filePath|
puts("Next file = #{filePath}")

Can the ruby spreadsheet gem wrap text?

Is there a way to use the ruby spreadsheet gem to produce a spreadsheet with a cell whose text is wrapped? (If not, is there some other way to do it?)
Thanks,
--Paul
p.s. In response to two good suggestions that unfortunately won't work for me, I should note:
1) I cannot convert my ruby application to JRuby at this time.
2) I am developing on Linux, not Windows.
Please try this for Ruby spreadsheet gem:
fmt = Spreadsheet::Format.new :text_wrap => true
sheet.row(y).set_format(x, fmt)
form here:
http://rubyforge.org/forum/forum.php?set=custom&forum_id=2920&style=nested&max_rows=50&submit=Change+View
I would agree with Phrogz in that you should use Win32OLE instead of the spreadsheet gem, if that is possible. This is how you would wrap a cell's text using Win32OLE:
worksheet.Range("A1").WrapText = true where worksheet references a specific worksheet.
Here is a more complete example:
xl = WIN32OLE.new('Excel.Application') # => opens Excel
wb = xl.Workbooks.Add(); # => adds a workbook
worksheet = wb.Worksheets(3) # => 3rd sheet (Excel starts at 1)
worksheet.Range("A1").value = "Hello, how do you do?"
worksheet.Range("A1").WrapText = true # => wraps the text
I hope this helps. I have used Win32OLE to work with Excel and like it.
P.S. Unless I missed it somewhere, it doesn't appear as if you can wrap text using the spreadsheet gem.
EDIT: Since question has added a Linux requirement, I'm adding this as a Linux answer.
Here is some code that I believe will work with POI Ruby Bindings:
h = Poi4r::HSSFWorkbook.new
s = h.createSheet("Sheet1")
r = s.createRow(0)
c = r.createCell(0)
t = h.createCellStyle()
t.setWrapText(true)
I have not tested this. It has been adapted from the POI Ruby page and quickguide for POI spreadsheet.
If JRuby is an option, then you can use the excellent POI library, which can do just about anything Excel can in its file format. It can indeed set cell wrapping option.
The following blog post, which I've had bookmarked for years, shows how you can make a Java API much more Ruby-like. It uses POI as an example.
http://mysterycoder.blogspot.com/2007/04/api-unickifying-with-jruby.html
It looks like the jruby-poi project has taken these ideas and made them a gem. https://github.com/kameeoze/jruby-poi
Edit: no need for JRuby. There are bindings for MRI: http://poi.apache.org/poi-ruby.html
Instead of using the spreadsheet gem--which generates a spreadsheet from scratch with limited capabilities--I suggest using Win32OLE to script Excel to modify an existing file. This is only suitable if you are on Windows and have a copy of Excel installed that can be opened by Ruby, and hence is usually unsuitable for a server environment.

Resources