sandrods / odf-report

Generates ODF files, given a template (.odt) and data, replacing tags

Home Page:http://sandrods.github.com/odf-report

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Get avaible placeholder

emmanuelmillionaer opened this issue · comments

First of all i want to say thanks for this great gem! I`m writing because i have problems to extend the gem! I tried to add a medthod that returns the avaible Placeholders but i had problems to achieve this, because i dont know exacly where i should put on.

When i for example call: ODFReport::Report.new("person.odt").placeholders

I would like that it returns ["name","telefon","street"]. Is this possible?

I looked at espacially at this method in report.rband thought in traversing through the documents nodes with Nokogiki! Would this be the right approach? Thanks!

 def parse_document(txt)
    doc = Nokogiri::XML(txt)
    yield doc
    txt.replace(doc.to_s)
 end

It would be a good place to start, except I guess you'd want to get the placeholders BEFORE generate the report.

Since the code above is called inside the update method, inside the generatemethod, you would be out of luck.

It looks like a lot of work.
You have to open the content.xmlfile to look for the [placeholders] (maybe using a regex).

Right now the code used to open the odt file and extract the xml`s is tied to the updating of the file.

You either have to refactor the File class to expose a (content) file for reading or duplicate the code and open it directly.

Not rocket science, but still a lot of work.

Let me know if I can help you anymore.

Regards,

Sandro

Im currently using odf-report 0.4.3 because i had problems with installing the new version because of rubyzip. To get the placholders i simply added to report.rb:

def get_placeholder
  %w(content.xml).each do |content_file|
      update_file_from_zip(@template, content_file) do |txt|
          return txt.scan(/\[(.*?)\]/)
      end
  end
end

And i can call it with:

report = ODFReport::Report.new("template_example.odt") do |r|
   placeholder = r.get_placeholder
   puts placeholder
end

The variable placeholder would now contain for example:

 ["name","telefon","street"]

Thanks @sandrods for the hint with the Regex! Maybe you have improvments for my code?

Cool

Your code is simple enough. I think I'll incorporate your solution.

As for rubyzip version, I've just released a new version 0.5.0 that uses rubyzip ~> 1.1.0

Please do try and see if it works for you

Sandro

@sandrods it would be a pleasure for me if you would incorporate my method! I also tried version 0.5.0 but even if i run a very simple test:

require 'odf-report'

report = ODFReport::Report.new("19.odt") do |r|
  r.add_field "Test", "This is a test"
end

puts report.generate("20.odt")

I get the following error:

C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/lib/zip/entry
.rb:334:in `check_c_dir_entry_static_header_length': undefined method `bytesize'
 for nil:NilClass (NoMethodError)
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/entry.rb:361:in `read_c_dir_entry'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/entry.rb:186:in `read_c_dir_entry'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/central_directory.rb:127:in `block in read_central_directory_entries'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/central_directory.rb:126:in `times'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/central_directory.rb:126:in `read_central_directory_entries'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/central_directory.rb:138:in `read_from_stream'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/file.rb:77:in `block in initialize'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/file.rb:76:in `open'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/file.rb:76:in `initialize'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/file.rb:96:in `new'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/file.rb:96:in `open'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/odf-report-0.5
.0/lib/odf-report/file.rb:20:in `update_files'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/odf-report-0.5
.0/lib/odf-report/report.rb:59:in `block in generate'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/odf-report-0.5
.0/lib/odf-report/file.rb:14:in `block in update_content'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/rubyzip-1.1.6/
lib/zip/output_stream.rb:60:in `write_buffer'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/odf-report-0.5
.0/lib/odf-report/file.rb:12:in `update_content'
        from C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/odf-report-0.5
.0/lib/odf-report/report.rb:57:in `generate'
        from odf_test.rb:9:in `<main>'

Its very sad because i would love to use the new version! Do you know how to fix it? Thanks and have a nice weekend!

@sandrods hi, is there something new related to this issue? I saw the other thread and also tried to solve it but had no success! Maybe i will switch to a old version of rubyzip! Wich version of rubzip did you test with? What do you recommend Thanks!

Hi,

I'm testing with 1.1.6.

Could you please send me an ODT file of yours which is throwing this error so I could test in my environment?

Thanks

Sandro

I tried your test,for example test_text.rb it generates a file in the folder result.I get no errors in the console so it seems to work! But when i try to open it with libreoffice or oppenoffice i get the errors:

erroro
errrr

The errors mean something like: The file is broken! The reason could be a manipulation or a faulty data transmission! Should openoffice try to repare it?

Then i click yes and the next error message pops out:

General Error
General Input/ Output Error

Looks like the problem is an incompatibility between your open office and rubyzip. Rubyzip can't open files generated by your OO (1st error) and your OO can't open files generated by rubyzip (last error).

I see you're still using open office which is pretty old. Is there any way you could try and use a more recent one, like LibreOffice? https://www.libreoffice.org

If you could send me some files for me to take a look at.

I have openoffice and libreoffice installed on my window pc and both show exactly the same error! I tried it with your example files in the test folder! I copied test_text.odt to my C:\Sites folder and opened it to see wheter it would give me an error! LibreOffice and OpenOffice opened the file without a problem then i wrote this little script:

require 'odf-report'
    report = ODFReport::Report.new("test_text.odt") do |r|
    r.add_field("TAG_01", "Hallo Süße")
 end

 report.generate("test_text2.odt")

It generates the correct file but it somehow only has 8Kb the original has 10kb. And when i try to open it with libreoffice or openoffice i get the error i described in my last post! I think you are right with the thought that maybe my rubyzip is not working correctly! Now i will try it on another windows pc with different versions of rubyzip! I hope i can fix my problem! Thanks for your help! Saudações

Ok now i tried it on my other windwos pc and it returns the same errors! I tried it with rubzip 1.1.0 and 1.1.6! To wich version of odf-report should i downgrade?

please send a corrupt file to sandrods at gmail dot com

Well, it's a Windows kind of problem.

The file you sent me (new_ticket.rb) was indeed corrupted. I could not open in my Mac. So I used your script to generate a new one, which opened correctly.

I then tried your script on a windows machine. The generated file was corrupt too.

So, the current status is: it does not work on windows. I'm looking into it and will post something as soon as I find out.

Released a new version 0.5.1
Please try, as this should resolve the issue.

Thanks @sandrods now it really works perfectly! I also tested the gem with rails and tried to save the binary output directly with paperclip: Like this it didnt worked:

  @document.file = report.generate

I had to change it to:

file = StringIO.new(report.generate.to_s)
class << file
  define_method(:original_filename) { "whatever.odt" }
  define_method(:content_type) { 'application/vnd.oasis.opendocument.text-template' }
end

@document.file = file

And in the model i had to switch of the validation:

 do_not_validate_attachment_file_type :file

Now it works! Did you tried something similar to save the files? I want to say thanks again for your help and wish you a nice day!

I use a class

class Attachment < StringIO
  attr_accessor :filepath

  def initialize(_filepath, *args)
    @filepath = _filepath
    super(*args)
  end

  def original_filename
    File.basename(filepath)
  end
end

and

@document.file = Attachment.new('whatever.odt', report.generate)

@sandrods

Am not able to generate my report file with the code below. Could you know where the issues is. My highest regards

require 'nokogiri'
require 'zip'
def print
@actuarial_science_first_year = ActuarialScienceFirstYear.find(params[:id])
report = ODFReport::Report.new("C:\Users\SOS2\Desktop\sos_templates\bas.odt") { |r|

r.add_field "NAME", @actuarial_science_first_year.name
r.add_field "ADMISSION_NO", @actuarial_science_first_year.admission_no
r.add_field "ACADEMIC_YEAR", @actuarial_science_first_year.academic_year

r.add_table("GRADES", @actuarial_science_first_year.grades, :header=>true) do |t|
t.add_column(:bsm_2103) { |item| "==> #{actuarial_science_first_year.bsm_2103.grading_af}"} 
t.add_column(:hrd_2101) { |item| "==> #{actuarial_science_first_year.hrd_2101.grading_af}" }
t.add_column(:bsm_1102) { |item| "==> #{actuarial_science_first_year.bsm_1102.grading_af}" }
t.add_column(:sas_1101) { |item| "==> #{actuarial_science_first_year.sas_1101.grading_af}" }
t.add_column(:sas_1190) { |item| "==> #{actuarial_science_first_year.sas_1190.grading_af}" }
t.add_column(:sma_2101) { |item| "==> #{actuarial_science_first_year.sma_2101.grading_af}" }
t.add_column(:bsm_2103) { |item| "==> #{actuarial_science_first_year.bsm_2103.grading_af}" }
t.add_column(:szl_2111) { |item| "==> #{actuarial_science_first_year.szl_2111.grading_af}" }
t.add_column(:sas_1201) { |item| "==> #{actuarial_science_first_year.sas_1201.grading_af}" }
t.add_column(:sas_1250) { |item| "==> #{actuarial_science_first_year.sas_1250.grading_af}" }
t.add_column(:sma_2102) { |item| "==> #{actuarial_science_first_year.sma_2102.grading_af}" }

end

send_data report.generate,
type: 'application/vnd.oasis.opendocument.text',
disposition: 'attachment',
filename: 'bas.odt'

report.generate("C:\Users\SOS2\Desktop\sos_transcripts")
}
end

Your problem may be here:

t.add_column(:bsm_2103) { |item| "==> #{actuarial_science_first_year.bsm_2103.grading_af}"}

You see, the |item| above points to an record/item of the @actuarial_science_first_year.grades collection.

What does it (@actuarial_science_first_year.grades) returns?

I imagine it should be somenthing like:

t.add_column(:bsm_2103) { |item| "==> #{item.bsm_2103.grading_af}" }

require "odf-report"
require 'nokogiri'
require 'zip'

def print

@actuarial_science_first_year = ActuarialScienceFirstYear.find(params[:id])

self.report = ODFReport::Report.new(Rails.root.join('app', 'reports', 'test.odt'))  do |r|

r.add_field(:student,         @actuarial_science_first_year.student)

end
end
send_data self.report.generate,
type: 'application/vnd.oasis.opendocument.text',
disposition: 'inline',
filename: 'report.odt'

This code keep giving me this error:

<top (required)>': undefined method `report' for main:Object (NoMethodError)

Hi,
Am trying the code below which gives me this error
NoMethodError (undefined method `grading' for 70:Fixnum):
70 is a numerical score for the exam bsm_2114
what could be the problem?

Thanks in advance

def grading
case @actuarial_science_first_year.bsm_2114
when 70..100 then puts "A"
when 60..69 then puts "B"
when 50..59 then puts "C"
when 40..49 then puts "D"
else puts "F"
end

r.add_field "BSM_2114", @actuarial_science_first_year.bsm_2114.grading