ruby-docx / docx

a ruby library/gem for interacting with .docx files
MIT License
431 stars 170 forks source link

Replace different placeholder text in each table cell #110

Closed HendrikZA closed 3 years ago

HendrikZA commented 3 years ago

Problem

I have a table with 5 cells in each row. Each cell has a different place holder text, e.g. email, delivered, opened, clicked, bounced.

Using your guide, here is a small snippet of the code I attempted to use to try replace place holder text with different names:

Substitute text in each cell of this new row

  new_row.cells.each do |cell|
    cell.paragraphs.each do |paragraph|
      paragraph.each_text_run do |text|
        text.substitute('email', 'newvalue')
        text.substitute('delivered', 'newvalue')
      end
    end
  end

This unfortunately does not work. It seems that only one place holder text.substitute works, e.g.

Substitute text in each cell of this new row

  new_row.cells.each do |cell|
    cell.paragraphs.each do |paragraph|
      paragraph.each_text_run do |text|
        text.substitute('email', 'newvalue')
        ~~text.substitute('delivered', 'newvalue')~~
      end
    end
  end

Solution

I'd like to be able to replace a value in each cell on a row with different placeholder texts.

Alternative solutions

None.

satoryu commented 3 years ago

Thank you for opening this issue. could you give a complete code and a docx file to reproduce this problem here?

HendrikZA commented 3 years ago

Thank you for opening this issue. could you give a complete code and a docx file to reproduce this problem here?

Thanks satoryu, I will provide complete code and a docx asap.

HendrikZA commented 3 years ago

Hi satoryu, this actually is working now :-) Please see my code below, and docx attached. I think the issue was the docx template my client gave me, because when I created a new docx and copied the table over to it, the code started working. Do you have any advice on how I can avoid the last row of placeholders from being inserted into the table please? events.docx

require 'docx'

user_events = [
  { email: 'harry@hogwarts.com', delivered: 'yes', opened: 'yes', clicked: 'yes', bounced: 'no' },
  { email: 'hermione@hogwarts.com', delivered: 'yes', opened: 'yes', clicked: 'no', bounced: 'no' },
  { email: 'hagrid@hogwarts.com', delivered: 'no', opened: 'no', clicked: 'no', bounced: 'yes' },
  { email: 'ron@hogwarts.com', delivered: 'no', opened: 'no', clicked: 'no', bounced: 'yes' }
]

# Create a Docx::Document object for our existing docx file
doc = Docx::Document.open('events.docx')

# Insert multiple lines of text at our bookmark
users_array = []
user_events.each { |user| users_array.push(user[:email]) }
doc.bookmarks['users'].insert_multiple_lines(users_array)

# Iterate over each table
doc.tables.each do |table|

  user_events.each do |user|

    last_row = table.rows.last

    # Copy last row and insert a new one before last row
    new_row = last_row.copy
    new_row.insert_before(last_row)

    # Substitute text in each cell of this new row
    new_row.cells.each do |cell|
      cell.paragraphs.each do |paragraph|
        paragraph.each_text_run do |text|
          text.substitute('_email_', user[:email])
          text.substitute('_delivered_', user[:delivered])
          text.substitute('_open_', user[:opened])
          text.substitute('_click_', user[:clicked])
          text.substitute('_bounce_', user[:bounced])
        end
      end
    end
  end
end

doc.save('events-edited.docx')
HendrikZA commented 3 years ago

hi satoryu, i'm happy for this to be closed. your gem has saved me a lot of work so thank you very much. i wish i could figure out how to remove the very last row of the table, as my placeholder cells end up there. i'm sure it will have something to do with using .each_with_index, checking if the last index has been reached and then not copying and inserting the placeholder row. i'm sure i'll figure it out somehow. cheer