openpyxl - कॉलम की चौड़ाई का आकार समायोजित करें


86

मेरे पास स्क्रिप्ट है जो एक CSV फ़ाइल को XLSX फ़ाइल में परिवर्तित कर रही है, लेकिन मेरे कॉलम का आकार बहुत कम है। हर बार मुझे डेटा पढ़ने के लिए उन्हें माउस से खींचना पड़ता है। क्या किसी को पता है कि कॉलम की चौड़ाई कैसे सेट करें openpyxl?

यहाँ कोड का उपयोग कर रहा हूँ।

#!/usr/bin/python2.6
import csv
from openpyxl import Workbook
from openpyxl.cell import get_column_letter

f = open('users_info_cvs.txt', "rU")

csv.register_dialect('colons', delimiter=':')

reader = csv.reader(f, dialect='colons')

wb = Workbook()
dest_filename = r"account_info.xlsx"

ws = wb.worksheets[0]
ws.title = "Users Account Information"

for row_index, row in enumerate(reader):
    for column_index, cell in enumerate(row):
        column_letter = get_column_letter((column_index + 1))
        ws.cell('%s%s'%(column_letter, (row_index + 1))).value = cell

wb.save(filename = dest_filename)

जवाबों:


86

आप इसे प्राप्त करने के लिए अनुमान लगा सकते हैं (या मोनो चौड़ाई फ़ॉन्ट का उपयोग कर सकते हैं)। मान लेते हैं कि डेटा एक नेस्टेड ऐरे है जैसे [['a1', 'a2'], ['b1', 'b2']]

हम प्रत्येक कॉलम में अधिकतम वर्ण प्राप्त कर सकते हैं। फिर उस पर चौड़ाई सेट करें। चौड़ाई बिल्कुल एक मोनोस्पेस फ़ॉन्ट की चौड़ाई है (यदि अन्य शैलियों को कम से कम नहीं बदल रहा है)। यहां तक ​​कि अगर आप एक चर चौड़ाई फ़ॉन्ट का उपयोग करते हैं तो यह एक सभ्य अनुमान है। यह सूत्रों के साथ काम नहीं करेगा।

from openpyxl.utils import get_column_letter

column_widths = []
for row in data:
    for i, cell in enumerate(row):
        if len(column_widths) > i:
            if len(cell) > column_widths[i]:
                column_widths[i] = len(cell)
        else:
            column_widths += [len(cell)]

for i, column_width in enumerate(column_widths):
    worksheet.column_dimensions[get_column_letter(i+1)].width = column_width

थोड़ा सा हैक लेकिन आपकी रिपोर्ट अधिक पठनीय होगी।


क्या आपको पता है कि यहाँ क्या समस्या है: stackoverflow.com/questions/32642026/…
Pyderman

1
जब मेरे पास सेल वैल्यू के रूप में इंट होता है, तो यह त्रुटि में टकराएगा क्योंकि इंट के पास कोई संपत्ति नहीं है, क्या इससे बचने का कोई तरीका है? धन्यवाद!
केविन झाओ

1
@KevinZhao थोड़ी देर से - लेकिन आपका सवाल यहाँ संबोधित किया गया है: stackoverflow.com/questions/2189800/…
jonyfries

56

बुफ्के ​​के जवाब की मेरी विविधता। सरणी के साथ शाखाओं में बंटने से बचा जाता है और खाली कोशिकाओं / स्तंभों की उपेक्षा करता है।

अब गैर-स्ट्रिंग सेल मूल्यों के लिए तय किया गया है।

ws = your current worksheet
dims = {}
for row in ws.rows:
    for cell in row:
        if cell.value:
            dims[cell.column] = max((dims.get(cell.column, 0), len(str(cell.value))))    
for col, value in dims.items():
    ws.column_dimensions[col].width = value

Openpyxl संस्करण 3.0.3 के रूप में आपको उपयोग करने की आवश्यकता है

 dims[cell.column_letter] = max((dims.get(cell.column_letter, 0), len(str(cell.value))))

Openpyxl पुस्तकालय के रूप में यदि आप column_dimensionsएक स्तंभ पत्र के बजाय एक संख्या से गुजरते हैं, तो एक टाइप-इयरराइड बढ़ाएगा , बाकी सब वही रह सकता है।


2
पंक्ति 6 ​​को स्तंभ पत्र का उपयोग करने के लिए सुधार किया जा सकता है: dims [cell.column_letter] = अधिकतम ((dims.get (cell.column_letter, 0), len (str (cell.value)))
जोनाथन '

38

सभी स्तंभों की चौड़ाई सेट करने के लिए और भी अधिक पाइथोनिक तरीका जो कम से कम ओपनपीक्सएल संस्करण 2.4.0 में काम करता है:

for column_cells in worksheet.columns:
    length = max(len(as_text(cell.value)) for cell in column_cells)
    worksheet.column_dimensions[column_cells[0].column].width = length

As_text फ़ंक्शन कुछ होना चाहिए जो मान को उचित लंबाई स्ट्रिंग में परिवर्तित करता है, जैसे कि पायथन 3:

def as_text(value):
    if value is None:
        return ""
    return str(value)

6
def as_text(value): return str(value) if value is not None else ""
थोरहंटर

4
@thorhunter len(cell.value or "") , अतिरिक्त कार्यों के लिए कोई ज़रूरत नहीं है
इरिना वेलिकोपोलकाया

2
@IrinaVelikopolskaya अगर cell.value लागू नहीं होता है __len__, तो यह अपवाद ( intया NoneTypeउदाहरण के लिए) को फेंक देगा
थोरहंटर

2
@IrinaVelikopolskaya डेटटाइम एक और उदाहरण है जहां किसी को अपवाद मिलता है। As_text फ़ंक्शन मेरे लिए सबसे अच्छा काम करता है।
सॉफ्टवेयर

11
ध्यान दें कि Openpyxl 2.6 के साथ, यह कोड क्रैश हो जाएगा TypeError: expected <class 'str'>। अब एक कॉलम नाम निर्दिष्ट करना होगा, अर्थात ws.column_dimensions[openpyxl.utils.get_column_letter(column_cells[0].column)].width = length.See bitbucket.org/openpyxl/openpyxl/issues/1240/…
phihag

10

मुझे मर्ज किए गए_स्केल्स की समस्या है और सही ढंग से काम नहीं करने पर ऑटोसेज़ करें, यदि आपके पास भी यही समस्या है, तो आप अगले विज्ञापन के साथ हल कर सकते हैं:

for col in worksheet.columns:
    max_length = 0
    column = col[0].column # Get the column name
    for cell in col:
        if cell.coordinate in worksheet.merged_cells: # not check merge_cells
            continue
        try: # Necessary to avoid error on empty cells
            if len(str(cell.value)) > max_length:
                max_length = len(cell.value)
        except:
            pass
    adjusted_width = (max_length + 2) * 1.2
    worksheet.column_dimensions[column].width = adjusted_width

7

उपरोक्त स्वीकार किए गए उत्तर का एक मामूली सुधार, जो मुझे लगता है कि अधिक पायथोनिक है (क्षमा मांगना अनुमति मांगने से बेहतर है)

column_widths = []
for row in workSheet.iter_rows():
    for i, cell in enumerate(row):
        try:
            column_widths[i] = max(column_widths[i], len(str(cell.value)))
        except IndexError:
            column_widths.append(len(str(cell.value)))

for i, column_width in enumerate(column_widths):
    workSheet.column_dimensions[get_column_letter(i + 1)].width = column_width

यह विचार करने की आवश्यकता है कि क्या cell.value एक स्ट्रिंग नहीं है। उदाहरण के लिए, यदि cell.value फ्लोट प्रकार का है, तो टाइप कास्टिंग की आवश्यकता होगी
wontleave

2
वाह जो 4 साल पहले था। आप ठीक हैं, हालांकि मैंने ठीक करने के लिए संपादन किया। बस एक कलाकार को स्ट्रिंग में जोड़ा गया।
shayst

5

Openpyxl 3.0.3 के साथ कॉलम को संशोधित करने का सबसे अच्छा तरीका डायमेंशनहॉल्ड ऑब्जेक्ट के साथ है, जो एक शब्दकोश है जो प्रत्येक कॉलम को कॉलमडिमिनेशन ऑब्जेक्ट में मैप करता है। ColumnDimension को बेस्टफिट , ऑटो_साइज (जो बेस्टफिट का उपनाम है) और चौड़ाई के रूप में पैरामीटर मिल सकता है । व्यक्तिगत रूप से, auto_size अपेक्षा के अनुरूप काम नहीं करता है और मुझे चौड़ाई का उपयोग करना था और यह सुनिश्चित करना था कि कॉलम के लिए सबसे अच्छी चौड़ाई है len(cell_value) * 1.23

प्रत्येक सेल का मान प्राप्त करने के लिए यह आवश्यक है कि प्रत्येक पर एक से अधिक पुनरावृति हो, लेकिन मैंने व्यक्तिगत रूप से इसका उपयोग नहीं किया क्योंकि मेरी परियोजना में मुझे केवल कार्यपत्रक लिखना था, इसलिए मुझे सीधे अपने डेटा पर प्रत्येक कॉलम में सबसे लंबा स्ट्रिंग मिला।

नीचे दिए गए उदाहरण में कॉलम आयामों को संशोधित करने का तरीका दिखाया गया है:

import openpyxl
from openpyxl.worksheet.dimensions import ColumnDimension, DimensionHolder
from openpyxl.utils import get_column_letter

wb = openpyxl.load_workbook("Example.xslx")
ws = wb["Sheet1"]

dim_holder = DimensionHolder(worksheet=ws)

for col in range(ws.min_column, ws.max_column + 1):
    dim_holder[get_column_letter(col)] = ColumnDimension(ws, min=col, max=col, width=20)

ws.column_dimensions = dim_holder

4

यह मेरा संस्करण @Virako का कोड स्निपेट है

def adjust_column_width_from_col(ws, min_row, min_col, max_col):

        column_widths = []

        for i, col in \
                enumerate(
                    ws.iter_cols(min_col=min_col, max_col=max_col, min_row=min_row)
                ):

            for cell in col:
                value = cell.value
                if value is not None:

                    if isinstance(value, str) is False:
                        value = str(value)

                    try:
                        column_widths[i] = max(column_widths[i], len(value))
                    except IndexError:
                        column_widths.append(len(value))

        for i, width in enumerate(column_widths):

            col_name = get_column_letter(min_col + i)
            value = column_widths[i] + 2
            ws.column_dimensions[col_name].width = value

और कैसे उपयोग करना है इस प्रकार है,

adjust_column_width_from_col(ws, 1,1, ws.max_column)

4

उपरोक्त सभी उत्तर एक समस्या उत्पन्न कर रहे हैं, जो कि col [0] है। कार्यपत्रक में नंबर वापस आ रहा है। कार्यपत्रक .column_dimensions [कॉलम] कॉलम के स्थान पर केवल 'ए', 'बी', 'सी' जैसे चरित्र को स्वीकार करता है। मैंने @ विराको का कोड संशोधित किया है और यह अब ठीक काम कर रहा है।

import re
import openpyxl
..
for col in _ws.columns:
    max_lenght = 0
    print(col[0])
    col_name = re.findall('\w\d', str(col[0]))
    col_name = col_name[0]
    col_name = re.findall('\w', str(col_name))[0]
    print(col_name)
    for cell in col:
        try:
            if len(str(cell.value)) > max_lenght:
                max_lenght = len(cell.value)
        except:
            pass
    adjusted_width = (max_lenght+2)
    _ws.column_dimensions[col_name].width = adjusted_width

3

हम संख्याओं को उनके ASCII मूल्यों में बदल सकते हैं और इसे column_dimension पैरामीटर को दे सकते हैं

import openpyxl as xl

work_book = xl.load_workbook('file_location')
sheet = work_book['Sheet1']
column_number = 2
column = str(chr(64 + column_number))
sheet.column_dimensions[column].width = 20
work_book.save('file_location')

3

जब ओपनबॉक्साइल अपडेट हुआ तो मुझे इसके उत्तर के ऊपर @ User3759685 बदलना पड़ा। मुझे एक त्रुटि मिल रही थी। खैर @phihag ने टिप्पणियों में भी इसकी सूचना दी

for column_cells in ws.columns:
    new_column_length = max(len(as_text(cell.value)) for cell in column_cells)
    new_column_letter = (openpyxl.utils.get_column_letter(column_cells[0].column))
    if new_column_length > 0:
        ws.column_dimensions[new_column_letter].width = new_column_length + 1

2

Openpyxl2.5.2a से नवीनतम 2.6.4 (अजगर 2.x समर्थन के लिए अंतिम संस्करण) के अपडेट के बाद, मुझे एक कॉलम की चौड़ाई को कॉन्फ़िगर करने में एक ही मुद्दा मिला।

मूल रूप से मैं हमेशा एक कॉलम के लिए चौड़ाई की गणना करता हूं (प्रत्येक कॉलम की चौड़ाई को बनाए रखने वाला एक तानाशाह है):

dims[cell.column] = max((dims.get(cell.column, 0), len(str(cell.value))))

बाद में मैं मूल आकार की तुलना में जल्द ही किसी चीज़ को बड़े पैमाने पर संशोधित कर रहा हूं, लेकिन अब आपको एक कॉलम का "लेटर" मान देना होगा, न कि एक इंट वैल्यू (नीचे का कोल वैल्यू है और सही अक्षर में अनुवादित है):

worksheet.column_dimensions[get_column_letter(col)].width = value +1 

यह दृश्यमान त्रुटि को ठीक करेगा और आपके कॉलम को सही चौड़ाई प्रदान करेगा;) इस मदद की उम्मीद है।


2

यहाँ पायथन 3.8 और ओपनपीएक्सएल 3.0.0 के लिए एक उत्तर दिया गया है।

मैंने get_column_letterफ़ंक्शन का उपयोग करने से बचने की कोशिश की, लेकिन असफल रहा।

यह समाधान नए शुरू किए गए असाइनमेंट एक्सप्रेशंस उर्फ "वालरस ऑपरेटर" का उपयोग करता है :

import openpyxl
from openpyxl.utils import get_column_letter

workbook = openpyxl.load_workbook("myxlfile.xlsx")

worksheet = workbook["Sheet1"]

MIN_WIDTH = 10
for i, column_cells in enumerate(worksheet.columns, start=1):
    width = (
        length
        if (length := max(len(str(cell_value) if (cell_value := cell.value) is not None else "")
                          for cell in column_cells)) >= MIN_WIDTH
        else MIN_WIDTH
    )
    worksheet.column_dimensions[get_column_letter(i)].width = width

1
max(len(str(cell.value)) for cell in filter(None, column_cells))मुझे स्पष्ट लगता है।
नूनो एंड्रे

0

यह एक गंदा फिक्स है। लेकिन Openpyxl वास्तव में समर्थन करता है auto_fit। लेकिन संपत्ति तक पहुंचने का कोई तरीका नहीं है।

import openpyxl
from openpyxl.utils import get_column_letter

wb = openpyxl.load_workbook("Example.xslx")
ws = wb["Sheet1"]
for i in range(1, ws.max_column+1):
    ws.column_dimensions[get_column_letter(i)].bestFit = True
    ws.column_dimensions[get_column_letter(i)].auto_size = True

0

चूंकि Openpyxl 2.6.1 में, इसे कॉलम अक्षर की आवश्यकता है, न कि कॉलम नंबर की, चौड़ाई निर्धारित करते समय।

 for column in sheet.columns:
    length = max(len(str(cell.value)) for cell in column)
    length = length if length <= 16 else 16
    sheet.column_dimensions[column[0].column_letter].width = length
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.