Openpyxl 复制具有命名范围的工作表

Openpyxl copy a sheet with named ranges

提问人:atallpa 提问时间:11/14/2023 更新时间:11/15/2023 访问量:38

问:

我可以复制我需要的工作表,但它没有复制命名范围,所以在单元格中我有 NAME 错误,因为公式使用该名称来进行微积分。当然,名称需要与地址匹配。 正确的方法是什么?

这是我的代码。

def write_to_template_sheet(input_filename, value_to_write):
    try:
        # Cargar el archivo Excel
        wb = openpyxl.load_workbook(input_filename)

        # Crear una copia de la hoja "Template"
        template_sheet = wb["Template"]
        new_sheet = wb.copy_worksheet(template_sheet)

        # Contar el número de hojas que comienzan con "P"
        hojas_con_p = [nombre for nombre in wb.sheetnames if nombre.startswith('P')]
        numero_hojas_con_p = len(hojas_con_p)

        # Renombrar la nueva hoja con "P" seguido del número de hojas con "P"
        new_sheet.title = f"P{numero_hojas_con_p +1}"

        # Copiar datos y formatos
        for row in template_sheet.iter_rows(min_row=1, max_row=template_sheet.max_row, min_col=1, max_col=template_sheet.max_column):
            
            for cell in row:
                    new_cell = new_sheet[cell.coordinate]
                    new_cell.value = cell.value
                   
        # Escribir el valor en la fila 31, columna 2 de la nueva hoja
        new_sheet.cell(row=31, column=2, value=value_to_write)

        # Guardar los cambios en el archivo
        wb.save(input_filename)

        st.success('Saved successfully')
        except Exception as e:
        st.error(f'Error: {str(e)}')


st.title("Create a project")


value_to_write = st.text_input("Name of the proyect", "",key="Project_Name")


if st.button("Save"):
    input_filename = "wbtool.xlsx"  # Nombre del archivo original
    write_to_template_sheet(input_filename, value_to_write)

我试过了

import streamlit as st
import openpyxl
from openpyxl import Workbook

wb = openpyxl.load_workbook('wbtool.xlsx')
sh = wb\['Template'\]
allnames=list(sh.defined_names.names)

st.write(allnames)

但我不知道如何将它用于复制,不仅是名称,还有地址。

python excel openpyxl streamlit

评论

0赞 moken 11/15/2023
注意你在 python 中的缩进。

答:

0赞 moken 11/15/2023 #1

您已使用 Openpyxl 'copy_worsheet' 函数制作了工作表的副本

new_sheet = wb.copy_worksheet(template_sheet)

因此,后面的命令遍历单元格并复制 # Copiar datos y formatos 中的值是多余的。本节不会做任何“copy_worksheet”还没有做过的事情。

对于定义的名称;创建新工作表后,您只需阅读并重新创建即可。
在此示例中,我假设模板定义的名称范围限定为该工作表,否则新创建的工作表将仅使用工作簿范围内的名称,而不会返回“NAME 错误”。
因此,在工作表上搜索要复制的定义名称,即 .
template_sheet.defined_names

for name, items in template_sheet.defined_names.items():

如果定义的名称的范围限定为工作簿,则需要改用工作簿对象定义的名称,因此需要修改代码。
为了获得详细信息,我们只需从“template_sheet”中读取定义的名称,然后为每个定义的名称重新创建并添加到新工作表中。
wb.defined_names

import openpyxl
import streamlit as st


def write_to_template_sheet(input_filename, value_to_write):
    try:
        # Cargar el archivo Excel
        wb = openpyxl.load_workbook(input_filename)

        # Crear una copia de la hoja "Template"
        template_sheet = wb["Template"]
        ### Copies the sheet here all styling and values (but not defined names)
        new_sheet = wb.copy_worksheet(template_sheet)

        # Contar el número de hojas que comienzan con "P"
        hojas_con_p = [nombre for nombre in wb.sheetnames if nombre.startswith('P')]
        numero_hojas_con_p = len(hojas_con_p)

        # Renombrar la nueva hoja con "P" seguido del número de hojas con "P"
        new_sheet.title = f"P{numero_hojas_con_p + 1}"

        ### Copy the defined names 
        for name, items in template_sheet.defined_names.items():
            ### change the sheet name in the coordinates
            coords = items.attr_text.replace(template_sheet.title, new_sheet.title)
            ### Create the new defined name for the new sheet using the same defined name e.g. data1 
            ### and the coords from the template sheet with sheet name changed
            new_dn = openpyxl.workbook.defined_name.DefinedName(
                name, attr_text=coords)
            ### Add the defined name scoped to the sheet
            new_sheet.defined_names.add(new_dn)

        ### This section is redundant cell values are already copied
        # Copiar datos y formatos
        # for row in template_sheet.iter_rows(min_row=1, max_row=template_sheet.max_row, min_col=1,
        #                                     max_col=template_sheet.max_column):
        #
        #     for cell in row:
        #         new_cell = new_sheet[cell.coordinate]
        #         new_cell.value = cell.value

        # Escribir el valor en la fila 31, columna 2 de la nueva hoja
        new_sheet.cell(row=31, column=2, value=value_to_write)

        # Guardar los cambios en el archivo
        wb.save(input_filename)

        st.success('Saved successfully')
    except Exception as e:
        st.error(f'Error: {str(e)}')