Combine planilhas do Excel em uma única tabela com uma coluna de planilha de origem
Combine planilhas que usam as mesmas colunas em uma única tabela do Excel, registrando de qual planilha cada linha veio. Uma pequena pasta de trabalho sintética permite verificar manualmente a ordem das linhas, as contagens e os totais.
Conteúdo verificado 2026.09.20Inclui arquivos de exemplo
Ver o sumário
A tradução foi feita com IA. Confira o código, as unidades e os valores junto com o original. A revisão por falantes nativos de cada idioma ainda não foi concluída. English
Para quem éEste guia é voltado a pessoas que recebem várias planilhas do Excel com estrutura semelhante e precisam de um único conjunto de dados consolidado sem alterar a pasta de trabalho original.
Preparação
Python 3.12 e um comando de terminal que inicie essa versão.
openpyxl instalado com python -m pip install openpyxl.
Uma pasta de trabalho em que os scripts possam criar pastas dentro de outputs.
As planilhas a serem combinadas devem usar os mesmos nomes de coluna na mesma ordem.
01Defina exatamente o que será combinado
O fluxo de trabalho combina planilhas selecionadas de uma pasta de trabalho em uma nova pasta de trabalho. Cada planilha de origem deve ter exatamente a mesma linha de cabeçalho, incluindo a ordem das colunas e o uso de maiúsculas e minúsculas. A saída adiciona source_sheet como primeira coluna para que cada registro preserve sua origem.
Linhas em branco são ignoradas. Linhas não vazias são copiadas na ordem das planilhas e, em seguida, na ordem original das linhas dentro de cada planilha. A pasta de trabalho de origem é aberta em modo somente leitura, e o resultado é gravado em uma pasta separada dentro de outputs.
02Crie uma pasta de trabalho sintética
A pasta de trabalho abaixo é sintética e foi criada especificamente para este artigo. Salve o script de preparação como create_excel_merge_demo.py. Ele cria três planilhas chamadas East, West e Online. Cada uma usa as colunas order_id, customer e amount.
python
from pathlib import Path
from openpyxl import Workbook
SOURCE_DIR = Path("outputs") / "excel_merge_demo"
SOURCE = SOURCE_DIR / "regional_orders.xlsx"
HEADERS = ["order_id", "customer", "amount"]
DATA = {
"East": [
["E001", "Ana", 120],
["E002", "Ben", 80],
],
"West": [
["W001", "Cara", 150],
["W002", "Dan", 70],
],
"Online": [
["O001", "Emi", 90],
[None, None, None],
["O002", "Finn", 110],
],
}
SOURCE_DIR.parent.mkdir(parents=True, exist_ok=True)
SOURCE_DIR.mkdir() # Stop if the synthetic source folder already exists.
workbook = Workbook()
for index, (sheet_name, rows) in enumerate(DATA.items()):
if index == 0:
sheet = workbook.active
sheet.title = sheet_name
else:
sheet = workbook.create_sheet(sheet_name)
sheet.append(HEADERS)
for row in rows:
sheet.append(row)
workbook.save(SOURCE)
text
python create_excel_merge_demo.py
Planilha
Linhas de dados não vazias
Total de amount
East
2
200
West
2
220
Online
2
200
Há 6 registros de dados não vazios no total. Os valores de amount somam 620: 120 + 80 + 150 + 70 + 90 + 110. Online contém deliberadamente uma linha completamente vazia entre seus dois registros para demonstrar que a lógica de combinação ignora linhas em branco.
03Determine manualmente a ordem esperada das linhas combinadas
O script lista explicitamente as planilhas como East, West e Online. Essa ordem determina a ordem dos registros combinados. Dentro de cada planilha, os registros permanecem na ordem original de cima para baixo.
source_sheet
order_id
customer
amount
East
E001
Ana
120
East
E002
Ben
80
West
W001
Cara
150
West
W002
Dan
70
Online
O001
Emi
90
Online
O002
Finn
110
A saída, portanto, tem 4 colunas e 7 linhas na planilha quando o cabeçalho é incluído: 1 linha de cabeçalho mais 6 linhas de dados. Os valores de source_sheet também oferecem uma verificação manual útil: East aparece duas vezes, West aparece duas vezes e Online aparece duas vezes.
04Combine as planilhas em uma nova pasta de trabalho
Salve o script a seguir como excel_merge_sheets.py. Ele abre a pasta de trabalho de origem em modo somente leitura, valida os nomes e cabeçalhos das planilhas selecionadas, ignora linhas completamente vazias e rejeita células com fórmulas para que as fórmulas não sejam silenciosamente separadas do contexto da pasta de trabalho original.
python
from pathlib import Path
from openpyxl import Workbook, load_workbook
SOURCE = Path("outputs") / "excel_merge_demo" / "regional_orders.xlsx"
OUTPUT_DIR = Path("outputs") / "excel_merge_result"
OUTPUT = OUTPUT_DIR / "merged_orders.xlsx"
SHEETS = ("East", "West", "Online")
OUTPUT_SHEET = "Combined"
SOURCE_COLUMN = "source_sheet"
def read_sheet_rows(sheet, expected_header=None):
first_row = next(
sheet.iter_rows(min_row=1, max_row=1, values_only=True),
None,
)
if first_row is None:
raise ValueError(f"Sheet is empty: {sheet.title}")
header = tuple(first_row)
if any(not isinstance(name, str) or not name.strip() for name in header):
raise ValueError(f"Invalid header in sheet: {sheet.title}")
if len(set(header)) != len(header):
raise ValueError(f"Duplicate header name in sheet: {sheet.title}")
if SOURCE_COLUMN in header:
raise ValueError(f"Reserved column already exists: {SOURCE_COLUMN}")
if expected_header is not None and header != expected_header:
raise ValueError(f"Header mismatch in sheet: {sheet.title}")
rows = []
for excel_row, values in enumerate(
sheet.iter_rows(min_row=2, max_col=len(header), values_only=True),
start=2,
):
if all(value is None for value in values):
continue
if any(isinstance(value, str) and value.startswith("=") for value in values):
raise ValueError(
f"Formula found in {sheet.title} row {excel_row}; "
"this example merges literal values only."
)
rows.append(tuple(values))
return header, rows
def main() -> None:
source_path = SOURCE.resolve(strict=True)
if not source_path.is_file():
raise ValueError("SOURCE must be an Excel file.")
if len(set(SHEETS)) != len(SHEETS):
raise ValueError("SHEETS contains a duplicate sheet name.")
source_workbook = load_workbook(
source_path,
read_only=True,
data_only=False,
)
try:
missing = [name for name in SHEETS if name not in source_workbook.sheetnames]
if missing:
raise ValueError(f"Missing sheets: {missing}")
expected_header = None
combined_rows = []
for sheet_name in SHEETS:
sheet = source_workbook[sheet_name]
header, rows = read_sheet_rows(sheet, expected_header)
if expected_header is None:
expected_header = header
for row in rows:
combined_rows.append((sheet_name, *row))
finally:
source_workbook.close()
OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
OUTPUT_DIR.mkdir() # Refuse to reuse an existing output folder.
output_workbook = Workbook()
output_sheet = output_workbook.active
output_sheet.title = OUTPUT_SHEET
output_sheet.append([SOURCE_COLUMN, *expected_header])
for row in combined_rows:
output_sheet.append(row)
output_workbook.save(OUTPUT)
check_workbook = load_workbook(OUTPUT, read_only=True, data_only=False)
try:
if check_workbook.sheetnames != [OUTPUT_SHEET]:
raise RuntimeError("Unexpected output worksheet structure.")
check_sheet = check_workbook[OUTPUT_SHEET]
written = list(check_sheet.iter_rows(values_only=True))
finally:
check_workbook.close()
expected = [(SOURCE_COLUMN, *expected_header), *combined_rows]
if written != expected:
raise RuntimeError("Saved workbook does not match the expected rows.")
print(f"Merged {len(SHEETS)} sheets into {len(combined_rows)} data rows.")
print(f"Verified {len(expected_header) + 1} columns and {len(combined_rows)} data rows.")
print(f"Output: {OUTPUT.as_posix()}")
if __name__ == "__main__":
main()
text
python excel_merge_sheets.py
05Compare o resultado esperado
Para a pasta de trabalho sintética, a saída deve conter exatamente uma planilha chamada Combined. Sua primeira linha deve ser source_sheet, order_id, customer, amount, seguida pelos 6 registros calculados anteriormente.
A saída esperada do console abaixo foi derivada manualmente a partir do código e dos dados sintéticos. Não é um log capturado de execução.
text
Merged 3 sheets into 6 data rows.
Verified 4 columns and 6 data rows.
Output: outputs/excel_merge_result/merged_orders.xlsx
Verificação
Resultado esperado
Planilhas de origem selecionadas
3
Linhas de dados combinadas
6
Colunas de saída
4
Linhas de East
2
Linhas de West
2
Linhas de Online
2
Total de amount
620
06Verifique a pasta de trabalho antes de usar dados reais
Abra merged_orders.xlsx e confirme que existe uma única planilha chamada Combined.
Confirme que source_sheet é a primeira coluna e que as três colunas originais vêm em seguida na mesma ordem.
Conte os registros por source_sheet. East, West e Online devem aparecer exatamente duas vezes cada.
Some a coluna amount manualmente ou com o Excel. O total esperado é 620.
Confirme que a linha em branco de Online não se tornou um registro vazio na saída combinada.
Execute o script novamente sem alterar OUTPUT_DIR. Ele deve parar com FileExistsError em vez de substituir o resultado anterior.
Em pastas de trabalho reais, altere SHEETS explicitamente em vez de combinar automaticamente todas as planilhas. Isso reduz a chance de incluir acidentalmente tabelas de consulta, anotações, planilhas ocultas ou planilhas de resumo que estejam armazenadas no mesmo arquivo.
07Reconheça erros comuns
Sintoma
O que verificar
ModuleNotFoundError: No module named openpyxl
Instale openpyxl no mesmo ambiente Python com python -m pip install openpyxl.
FileNotFoundError
Verifique SOURCE e o diretório de trabalho do terminal. Neste exemplo, execute primeiro a preparação da pasta de trabalho sintética.
Missing sheets
Verifique exatamente os nomes em SHEETS, incluindo espaços e o uso de maiúsculas e minúsculas.
Header mismatch
Confirme que todas as planilhas selecionadas usam nomes de coluna idênticos na mesma ordem.
Reserved column already exists
Renomeie a coluna de origem chamada source_sheet ou altere SOURCE_COLUMN para um nome que não entre em conflito.
Formula found
Decida como as fórmulas devem ser tratadas antes da combinação. Este tutorial para deliberadamente em vez de copiar expressões de fórmulas sem contexto.
FileExistsError
A pasta de saída já existe. Revise o resultado anterior e use um novo destino em vez de sobrescrevê-lo.
Se o salvamento ou a verificação falharem depois que OUTPUT_DIR tiver sido criado, a pasta ou a pasta de trabalho poderá permanecer como um resultado parcial. Trate-o como não verificado e use um novo destino depois de corrigir o problema.
08Entenda os limites
O script é destinado a planilhas de dados retangulares com uma única linha de cabeçalho. Ele não lida com cabeçalhos de várias linhas, células de cabeçalho mescladas, tabelas dinâmicas, gráficos, imagens ou planilhas em que várias tabelas não relacionadas compartilham a mesma planilha.
Somente os valores das células são consolidados. Formatos numéricos, fontes, preenchimentos, formatação condicional, regras de validação, hiperlinks, comentários, fórmulas, alturas de linha, larguras de coluna e configurações em nível de planilha não são reproduzidos. Valores literais de data e numéricos podem ser mantidos como valores, mas a formatação de exibição original não é copiada.
O script também carrega todas as tuplas de linhas combinadas na memória do Python antes de criar a pasta de trabalho de saída. Isso é conveniente para este pequeno fluxo de trabalho verificado, mas pode não ser adequado para pastas de trabalho muito grandes. Em arquivos grandes, um projeto de streaming com saída write-only e validação incremental separada reduziria o uso de memória.
Foram contados manualmente 2 registros não vazios em East, 2 em West e 2 em Online, totalizando 6 registros combinados.
Foram calculados manualmente os totais de amount das planilhas como 200, 220 e 200, resultando em 620 no total.
Foi derivada manualmente a ordem esperada da saída: primeiro as linhas de East, depois West e, por fim, Online, com a linha completamente vazia de Online ignorada.
O código foi inspecionado para confirmar que a pasta de trabalho de origem é aberta em modo somente leitura e o resultado é gravado em uma pasta outputs separada.
Foram inspecionadas as verificações de cabeçalho, a verificação da coluna reservada source_sheet, o tratamento de linhas em branco, a rejeição de fórmulas e a comparação de linhas após o salvamento.
Foram derivadas manualmente as 4 colunas de saída, as 6 linhas de dados e as mensagens esperadas do console.
Limites da verificação
O código não foi executado pelo autor desta resposta; nenhum arquivo XLSX foi criado nem aberto aqui.
Pastas de trabalho com fórmulas, células mescladas, formatação, datas, hiperlinks, planilhas ocultas, arquivos corrompidos e pastas de trabalho muito grandes não foram testados.
O comportamento do openpyxl na pasta de trabalho sintética foi inferido a partir do código, mas não foi confirmado em um ambiente de execução Python.
As URLs da documentação oficial foram fornecidas com base em locais de documentação conhecidos, mas não foram verificadas ao vivo.
Encontre linhas com correspondência exata nas quatro colunas e reúna-as em um novo arquivo do Excel junto com seus números de linha originais. Revise cada grupo de duplicatas, incluindo a primeira ocorrência.
Antes de transformar uma tabela em texto, alinhe o objeto, o período, o denominador e a unidade. Use uma tabela sintética de resultados mensais para verificar um valor que mudou de 80 % para 82 % e uma conversão de unidades, e depois monte uma lista de verificação reutilizável.
Combine vários PDFs em um único arquivo, extraia um intervalo inclusivo de páginas para um segundo arquivo e verifique a contagem e a ordem das páginas resultantes. Um conjunto sintético de páginas em branco com dimensões deliberadamente diferentes torna o resultado verificável manualmente.