Enhanced adjusting exported columns' width
This commit is contained in:
@@ -6202,6 +6202,7 @@ def create_excel_export(selected_columns, column_names, filters):
|
|||||||
try:
|
try:
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
from openpyxl.styles import Font, Alignment, PatternFill
|
from openpyxl.styles import Font, Alignment, PatternFill
|
||||||
|
from openpyxl.utils import get_column_letter
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(f"❌ openpyxl import error: {e}")
|
print(f"❌ openpyxl import error: {e}")
|
||||||
print("💡 Install openpyxl: pip install openpyxl")
|
print("💡 Install openpyxl: pip install openpyxl")
|
||||||
@@ -6386,19 +6387,64 @@ def create_excel_export(selected_columns, column_names, filters):
|
|||||||
print(f"⚠️ Error setting cell value for {column_key}: {cell_error}")
|
print(f"⚠️ Error setting cell value for {column_key}: {cell_error}")
|
||||||
cell.value = ''
|
cell.value = ''
|
||||||
|
|
||||||
# Auto-adjust column widths
|
# Auto-adjust column widths based on content and header
|
||||||
for column in ws.columns:
|
for col_idx, column_key in enumerate(selected_columns, 1):
|
||||||
|
column_letter = get_column_letter(col_idx)
|
||||||
max_length = 0
|
max_length = 0
|
||||||
column_letter = column[0].column_letter
|
|
||||||
for cell in column:
|
# Get header name length
|
||||||
|
header_name = column_names.get(column_key, column_key)
|
||||||
|
max_length = len(str(header_name))
|
||||||
|
|
||||||
|
# Check content in all rows (sample first 100 rows for performance)
|
||||||
|
for row_idx in range(2, min(102, ws.max_row + 1)):
|
||||||
|
cell = ws.cell(row=row_idx, column=col_idx)
|
||||||
try:
|
try:
|
||||||
if len(str(cell.value)) > max_length:
|
cell_value = str(cell.value) if cell.value else ''
|
||||||
max_length = len(str(cell.value))
|
# For HYPERLINK formulas, extract the display text
|
||||||
|
if cell_value.startswith('=HYPERLINK'):
|
||||||
|
# Extract text between last quotes: HYPERLINK("url","display_text")
|
||||||
|
import re
|
||||||
|
match = re.search(r',"([^"]+)"\)$', cell_value)
|
||||||
|
if match:
|
||||||
|
cell_value = match.group(1)
|
||||||
|
|
||||||
|
if len(cell_value) > max_length:
|
||||||
|
max_length = len(cell_value)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
adjusted_width = min(max_length + 2, 50)
|
|
||||||
|
# Set width based on column type with reasonable limits
|
||||||
|
# Define optimal widths for specific column types
|
||||||
|
column_width_rules = {
|
||||||
|
'employee_id': {'min': 8, 'max': 15},
|
||||||
|
'employee_name': {'min': 20, 'max': 30},
|
||||||
|
'location_name': {'min': 15, 'max': 35},
|
||||||
|
'status': {'min': 12, 'max': 20},
|
||||||
|
'check_in_date': {'min': 12, 'max': 15},
|
||||||
|
'check_in_time': {'min': 10, 'max': 12},
|
||||||
|
'qr_address': {'min': 20, 'max': 40},
|
||||||
|
'address': {'min': 20, 'max': 45},
|
||||||
|
'device_info': {'min': 12, 'max': 20},
|
||||||
|
'ip_address': {'min': 14, 'max': 18},
|
||||||
|
'user_agent': {'min': 15, 'max': 30},
|
||||||
|
'latitude': {'min': 12, 'max': 15},
|
||||||
|
'longitude': {'min': 12, 'max': 15},
|
||||||
|
'accuracy': {'min': 10, 'max': 15},
|
||||||
|
'location_accuracy': {'min': 10, 'max': 15}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get rules for this column or use defaults
|
||||||
|
rules = column_width_rules.get(column_key, {'min': 10, 'max': 40})
|
||||||
|
|
||||||
|
# Calculate adjusted width: add 2 for padding, respect min/max
|
||||||
|
adjusted_width = max_length + 2
|
||||||
|
adjusted_width = max(rules['min'], min(adjusted_width, rules['max']))
|
||||||
|
|
||||||
ws.column_dimensions[column_letter].width = adjusted_width
|
ws.column_dimensions[column_letter].width = adjusted_width
|
||||||
|
|
||||||
|
print(f"📏 Column {column_letter} ({column_key}): set width to {adjusted_width} (content: {max_length} chars)")
|
||||||
|
|
||||||
# Save to BytesIO
|
# Save to BytesIO
|
||||||
excel_buffer = io.BytesIO()
|
excel_buffer = io.BytesIO()
|
||||||
wb.save(excel_buffer)
|
wb.save(excel_buffer)
|
||||||
@@ -6448,6 +6494,7 @@ def create_excel_export_ordered(selected_columns, column_names, filters):
|
|||||||
try:
|
try:
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
from openpyxl.styles import Font, Alignment, PatternFill
|
from openpyxl.styles import Font, Alignment, PatternFill
|
||||||
|
from openpyxl.utils import get_column_letter
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(f"❌ openpyxl import error: {e}")
|
print(f"❌ openpyxl import error: {e}")
|
||||||
print("💡 Install openpyxl: pip install openpyxl")
|
print("💡 Install openpyxl: pip install openpyxl")
|
||||||
@@ -6647,19 +6694,64 @@ def create_excel_export_ordered(selected_columns, column_names, filters):
|
|||||||
print(f"⚠️ Error setting cell value for {column_key}: {cell_error}")
|
print(f"⚠️ Error setting cell value for {column_key}: {cell_error}")
|
||||||
cell.value = ''
|
cell.value = ''
|
||||||
|
|
||||||
# Auto-adjust column widths
|
# Auto-adjust column widths based on content and header
|
||||||
for column in ws.columns:
|
for col_idx, column_key in enumerate(selected_columns, 1):
|
||||||
|
column_letter = get_column_letter(col_idx)
|
||||||
max_length = 0
|
max_length = 0
|
||||||
column_letter = column[0].column_letter
|
|
||||||
for cell in column:
|
# Get header name length
|
||||||
|
header_name = column_names.get(column_key, column_key)
|
||||||
|
max_length = len(str(header_name))
|
||||||
|
|
||||||
|
# Check content in all rows (sample first 100 rows for performance)
|
||||||
|
for row_idx in range(2, min(102, ws.max_row + 1)):
|
||||||
|
cell = ws.cell(row=row_idx, column=col_idx)
|
||||||
try:
|
try:
|
||||||
if len(str(cell.value)) > max_length:
|
cell_value = str(cell.value) if cell.value else ''
|
||||||
max_length = len(str(cell.value))
|
# For HYPERLINK formulas, extract the display text
|
||||||
|
if cell_value.startswith('=HYPERLINK'):
|
||||||
|
# Extract text between last quotes: HYPERLINK("url","display_text")
|
||||||
|
import re
|
||||||
|
match = re.search(r',"([^"]+)"\)$', cell_value)
|
||||||
|
if match:
|
||||||
|
cell_value = match.group(1)
|
||||||
|
|
||||||
|
if len(cell_value) > max_length:
|
||||||
|
max_length = len(cell_value)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
adjusted_width = min(max_length + 2, 50)
|
|
||||||
|
# Set width based on column type with reasonable limits
|
||||||
|
# Define optimal widths for specific column types
|
||||||
|
column_width_rules = {
|
||||||
|
'employee_id': {'min': 8, 'max': 15},
|
||||||
|
'employee_name': {'min': 20, 'max': 30},
|
||||||
|
'location_name': {'min': 15, 'max': 35},
|
||||||
|
'status': {'min': 12, 'max': 20},
|
||||||
|
'check_in_date': {'min': 12, 'max': 15},
|
||||||
|
'check_in_time': {'min': 10, 'max': 12},
|
||||||
|
'qr_address': {'min': 20, 'max': 40},
|
||||||
|
'address': {'min': 20, 'max': 45},
|
||||||
|
'device_info': {'min': 12, 'max': 20},
|
||||||
|
'ip_address': {'min': 14, 'max': 18},
|
||||||
|
'user_agent': {'min': 15, 'max': 30},
|
||||||
|
'latitude': {'min': 12, 'max': 15},
|
||||||
|
'longitude': {'min': 12, 'max': 15},
|
||||||
|
'accuracy': {'min': 10, 'max': 15},
|
||||||
|
'location_accuracy': {'min': 10, 'max': 15}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get rules for this column or use defaults
|
||||||
|
rules = column_width_rules.get(column_key, {'min': 10, 'max': 40})
|
||||||
|
|
||||||
|
# Calculate adjusted width: add 2 for padding, respect min/max
|
||||||
|
adjusted_width = max_length + 2
|
||||||
|
adjusted_width = max(rules['min'], min(adjusted_width, rules['max']))
|
||||||
|
|
||||||
ws.column_dimensions[column_letter].width = adjusted_width
|
ws.column_dimensions[column_letter].width = adjusted_width
|
||||||
|
|
||||||
|
print(f"📏 Column {column_letter} ({column_key}): set width to {adjusted_width} (content: {max_length} chars)")
|
||||||
|
|
||||||
# Save to BytesIO
|
# Save to BytesIO
|
||||||
excel_buffer = io.BytesIO()
|
excel_buffer = io.BytesIO()
|
||||||
wb.save(excel_buffer)
|
wb.save(excel_buffer)
|
||||||
|
|||||||
Reference in New Issue
Block a user