Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-height #69

Open
jurriaan opened this issue Mar 28, 2012 · 55 comments
Open

Auto-height #69

jurriaan opened this issue Mar 28, 2012 · 55 comments

Comments

@jurriaan
Copy link
Collaborator

Axlsx has support for autowidth, but what do you think about auto height?, for columns containing multiple rows of text.

@cj
Copy link

cj commented Jul 25, 2012

+1

6 similar comments
@horaciob
Copy link

horaciob commented Nov 7, 2012

+1

@scanferla
Copy link

+1

@morkevicius
Copy link

+1

@dszczyt
Copy link

dszczyt commented Feb 13, 2013

+1

@indrekj
Copy link

indrekj commented Apr 26, 2013

+1

@murphysw
Copy link

+1

@rafadc
Copy link

rafadc commented Oct 2, 2013

Can't you accomplish this through word wrap?

@osegrums
Copy link

osegrums commented Oct 7, 2013

+1

4 similar comments
@rvsingh
Copy link

rvsingh commented Nov 7, 2013

+1

@rujaun
Copy link

rujaun commented Nov 20, 2013

+1

@panasyuk
Copy link

+1

@songjiayang
Copy link

+1

@hofdesu
Copy link

hofdesu commented Mar 31, 2014

+1 Is there any workaround for this in the meantime that people have come up with?

@jurriaan
Copy link
Collaborator Author

You can just use word wrap or you can count the number of lines and multiply that by the +/- the font size

@trestles
Copy link

trestles commented Apr 1, 2014

could you do a gist for handling this? or is there a way to query the worksheet for the number of rows given a fontSize and a certrain string of text?

@hofdesu
Copy link

hofdesu commented Apr 8, 2014

Yeah, so I was using wordwrap but still had rows and words cut off.

Ended up writing a helper to do similar to what you suggest @jurriaan . Checked the cells autowidth value, then taking in to account that, any new lines, and a bit of a buffer for whitespace at the end of each line, assign a new row hight.
....
A bit (quite) flakey, but quick, and it will do the trick in the short term.

@jfrux
Copy link

jfrux commented Mar 5, 2015

+1

1 similar comment
@Wolfer
Copy link

Wolfer commented Jun 4, 2015

+1

@jweissig
Copy link

@hofdesu can you share the helper re: calculating the height?

@jmuheim
Copy link

jmuheim commented Nov 11, 2015

@hofdesu yes, could you please show your helper?

@sathibabu-nyros
Copy link

+1

4 similar comments
@aschyiel
Copy link

aschyiel commented Mar 1, 2016

+1

@arturtr
Copy link

arturtr commented Jul 13, 2016

+1

@raphaottoni
Copy link

+1

@codexorange
Copy link

+1

@vjustov
Copy link

vjustov commented Dec 18, 2016

Hello @randym, how one should approach a PR for this feature? what's to take into account?

@xjcbruce
Copy link

+1

2 similar comments
@flashharry82
Copy link

+1

@karamosky
Copy link

+1

@jbrodie
Copy link

jbrodie commented Mar 5, 2017

+1

18 similar comments
@HenryTimelessness
Copy link

+1

@TimotheeVille
Copy link

+1

@gilangmugnirespaty
Copy link

+1

@AndreFSilveira
Copy link

+1

@eugene-ershov
Copy link

+1

@alexeymoshkin
Copy link

+1

@h0jeZvgoxFepBQ2C
Copy link

+1

@leoduquesnel
Copy link

+1

@kirylrb
Copy link

kirylrb commented May 25, 2018

+1

@rusllonrails
Copy link

rusllonrails commented May 26, 2018

+1

@kleyy
Copy link

kleyy commented Jun 6, 2018

+1

@MPM10223
Copy link

MPM10223 commented Jun 8, 2018

+1

@marcinwierzbicki
Copy link

+1

@sahilchopra
Copy link

+1

@mathieugagne
Copy link

+1

@pohodnya
Copy link

+1

@quochien
Copy link

+1

@keangnage
Copy link

+1

@ykessler
Copy link

Re calculating height manually, see #125 (comment) for help in calculating text width

@benkoshy
Copy link

benkoshy commented Jan 19, 2022

For anyone wanting a cheap hack to get a rough estimate of the row height, here's what worked for me.

def set_row_height(row, text)
	column_width = row.worksheet.column_info[8].width # column 8 is where my data lives
	length_of_text = if text.nil?
					0
				   else
				 	text.length
				 end

	row_height = length_of_text / 52 * 14
	row.height = row_height
end
def get_line_item_data(line_item, line_item_type, sheet)
   line_item_data = [line_item.created_at.strftime("%m/%d/%Y"), line_item.id, line_item.item_index, line_item.quote_id, line_item.quote.project_name, line_item_type , line_item.hours, line_item.price, line_item.scope_description ]
   line_item_data
end

wb = xlsx_package.workbook
wb.add_worksheet(name: "Line Items") do |sheet|	
	sheet.add_row ["Created At", "Line Item Id", "Line Item Index", "Quote ID", "Project Name", "Line Item Type", "Hours", "Price", "Description", "Links......"]

	@line_items.each do |line_item|
		row = sheet.add_row(get_line_item_data(line_item, line_item_type, sheet), style: wrap_text)
		set_row_height(row, line_item.scope_description )
	end
end

Watch out - we've hard coded some values, and remember, the size of the text can change. Overall, it might give you some ideas on where to start. Is it robust? No. Is it pretty? It's just good enough.

@jprince
Copy link

jprince commented Mar 7, 2023

@benkoshy can you please clarify the magic numbers? I assume 14 is font size? How did you get the 52 coefficient? Is that supposed to be column_width?

@benkoshy
Copy link

benkoshy commented Mar 7, 2023

@jprince sorry mate i completely forgot. I hacked out a solution, but it probably does deserve a fuller treatment: some sort of PR in the main library.

@jbrodie
Copy link

jbrodie commented Mar 7, 2023

No worries. It would be a great option to be able to have in this library though.

@jprince
Copy link

jprince commented Mar 8, 2023

Here's what I ended up implementing. Hopefully it can be of use to someone else in the future...

It loops over each column in a row, taking the cell value, splitting the string on line breaks (in case the content contains line breaks), then compares the length of each text_line to the column width to determine how many physical lines it spans in the sheet. Then add them together for each cell and take the cell with the most total text_lines and use the font size to translate that to a row height.

def infer_row_height(row)
  physical_lines = row.each_with_index.map do |cell, column_index|
    text = cell.value
    column_width = row.worksheet.column_info[column_index].width

    text_lines = text.to_s.lines # handle newlines entered by the user
    text_lines.map { |line| (string_width(line, row) / column_width.to_f).ceil }.sum
  end.max
  row.height = (physical_lines * FONT_SIZE) + LINE_PADDING # in my case 11, 5
end

# Copied directly from caxlsx: https://github.com/caxlsx/caxlsx/blob/ebd11df1c11e3fe3eb0870e4c43d7ff8771ffe0d/lib/axlsx/workbook/worksheet/cell.rb#L437
def string_width(string, row)
  font_scale = Style::FONT_SIZE / row.worksheet.workbook.font_scale_divisor
  (string.to_s.size + 3) * font_scale
end

In code for generating the workbook:

data.each { |d| sheet.add_row(d) }
sheet.column_widths(*columns.map { |c| c[:width] }) # must be set after adding data

# needs to run after column_widths is set
sheet.rows.each { |row| infer_row_height(row) }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests