【问题标题】:From password-protected Excel file to pandas DataFrame从受密码保护的 Excel 文件到 pandas DataFrame
【发布时间】:2013-02-23 11:17:35
【问题描述】:

我可以用这个打开一个受密码保护的 Excel 文件:

import sys
import win32com.client
xlApp = win32com.client.Dispatch("Excel.Application")
print "Excel library version:", xlApp.Version
filename, password = sys.argv[1:3]
xlwb = xlApp.Workbooks.Open(filename, Password=password)
# xlwb = xlApp.Workbooks.Open(filename)
xlws = xlwb.Sheets(1) # counts from 1, not from 0
print xlws.Name
print xlws.Cells(1, 1) # that's A1

我不确定如何将信息传输到 pandas 数据框。我需要一个一个地读取单元格,还是有一种方便的方法可以做到这一点?

【问题讨论】:

  • xlws 是否有 RowRowCount(或其他名称) - 如果有,则循环遍历行数并构建列表列表...然后在上面使用pandas.DataFrame...(抱歉 - 不要使用 Windows - 所以我自己不能尝试)

标签: python excel pandas


【解决方案1】:

假设起始单元格为 (StartRow, StartCol),结束单元格为 (EndRow, EndCol),我发现以下方法对我有用:

# Get the content in the rectangular selection region
# content is a tuple of tuples
content = xlws.Range(xlws.Cells(StartRow, StartCol), xlws.Cells(EndRow, EndCol)).Value 

# Transfer content to pandas dataframe
dataframe = pandas.DataFrame(list(content))

注意:Excel 单元格 B5 在 win32com 中作为第 5 行第 2 列给出。此外,我们需要 list(...) 将元组元组转换为元组列表,因为元组元组没有 pandas.DataFrame 构造函数。

【讨论】:

  • 范围也可以使用字母,例如:xlws.Range("A1:H100").Value.
【解决方案2】:

来自 David Hamann 的网站(所有学分归他所有) https://davidhamann.de/2018/02/21/read-password-protected-excel-files-into-pandas-dataframe/

使用 xlwings,打开文件将首先启动 Excel 应用程序,以便您输入密码。

import pandas as pd
import xlwings as xw

PATH = '/Users/me/Desktop/xlwings_sample.xlsx'
wb = xw.Book(PATH)
sheet = wb.sheets['sample']

df = sheet['A1:C4'].options(pd.DataFrame, index=False, header=True).value
df

【讨论】:

【解决方案3】:

假设您可以使用 win32com API 将加密文件保存回磁盘(我意识到这可能会破坏目的),那么您可以立即调用顶级 pandas 函数read_excel。不过,您需要先安装xlrd(适用于Excel 2003)、xlwt(也适用于2003)和openpyxl(适用于Excel 2007)的某种组合。 Here 是用于读取 Excel 文件的文档。目前 pandas 不支持使用 win32com API 读取 Excel 文件。如果您愿意,欢迎来到open up a GitHub issue

【讨论】:

  • 我不能再测试它了,因为我目前不在一个能让我这样做的环境中工作。如果您提供示例代码并向我保证它有效,我会将这个或任何其他答案标记为已接受。 :7)
  • 我不知道如何使用 win32com API,所以您必须自己弄清楚,但是如果您查看我提供链接的文档,它会给出正确操作的说明你想要什么。此处无需复制示例代码,您可以在那里阅读。
【解决方案4】:

根据@ikeoddy 提供的建议,这应该将各个部分放在一起:

How to open a password protected excel file using python?

# Import modules
import pandas as pd
import win32com.client
import os
import getpass

# Name file variables
file_path = r'your_file_path'
file_name = r'your_file_name.extension'

full_name = os.path.join(file_path, file_name)
# print(full_name)

Getting command-line password input in Python

# You are prompted to provide the password to open the file
xl_app = win32com.client.Dispatch('Excel.Application')
pwd = getpass.getpass('Enter file password: ')

Workbooks.Open Method (Excel)

xl_wb = xl_app.Workbooks.Open(full_name, False, True, None, pwd)
xl_app.Visible = False
xl_sh = xl_wb.Worksheets('your_sheet_name')

# Get last_row
row_num = 0
cell_val = ''
while cell_val != None:
    row_num += 1
    cell_val = xl_sh.Cells(row_num, 1).Value
    # print(row_num, '|', cell_val, type(cell_val))
last_row = row_num - 1
# print(last_row)

# Get last_column
col_num = 0
cell_val = ''
while cell_val != None:
    col_num += 1
    cell_val = xl_sh.Cells(1, col_num).Value
    # print(col_num, '|', cell_val, type(cell_val))
last_col = col_num - 1
# print(last_col)

ikeoddy 的回答:

content = xl_sh.Range(xl_sh.Cells(1, 1), xl_sh.Cells(last_row, last_col)).Value
# list(content)
df = pd.DataFrame(list(content[1:]), columns=content[0])
df.head()

python win32 COM closing excel workbook

xl_wb.Close(False)

【讨论】:

  • 不用手动计算行数和列数,简单使用xl_sh..UsedRange.Rows.Countxl_sh.UsedRange.Columns.Count
【解决方案5】:

简单的解决方案

import io
import pandas as pd
import msoffcrypto

passwd = 'xyz'

decrypted_workbook = io.BytesIO()
with open(i, 'rb') as file:
    office_file = msoffcrypto.OfficeFile(file)
    office_file.load_key(password=passwd)
    office_file.decrypt(decrypted_workbook)

df = pd.read_excel(decrypted_workbook, sheet_name='abc')

pip install --user msoffcrypto-tool

将每个excel的所有工作表从目录和子目录中导出为单独的csv文件

from glob import glob
PATH = "Active Cons data"

# Scaning all the excel files from directories and sub-directories
excel_files = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.xlsx'))] 

for i in excel_files:
    print(str(i))
    decrypted_workbook = io.BytesIO()
    with open(i, 'rb') as file:
        office_file = msoffcrypto.OfficeFile(file)
        office_file.load_key(password=passwd)
        office_file.decrypt(decrypted_workbook)

    df = pd.read_excel(decrypted_workbook, sheet_name=None)
    sheets_count = len(df.keys())
    sheet_l = list(df.keys())  # list of sheet names
    print(sheet_l)
    for i in range(sheets_count):
        sheet = sheet_l[i]
        df = pd.read_excel(decrypted_workbook, sheet_name=sheet)
        new_file = f"D:\\all_csv\\{sheet}.csv"
        df.to_csv(new_file, index=False)

【讨论】:

    【解决方案6】:

    添加到@Maurice 答案以获取工作表中的所有单元格,而无需指定范围

    wb = xw.Book(PATH, password='somestring')
    sheet = wb.sheets[0] #get first sheet
    
    #sheet.used_range.address returns string of used range
    df = sheet[sheet.used_range.address].options(pd.DataFrame, index=False, header=True).value
    

    【讨论】:

    • AttributeError: '' 对象没有属性 'used_range'
    • 我最近遇到了类似的错误,但后来我不得不升级到 Office 365,所以这可能是我的问题。这里的代码使用的是 Office 2016。
    • 也许,我也在使用 Office 365。
    猜你喜欢
    • 2011-02-06
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2018-12-18
    • 2015-11-15
    相关资源
    最近更新 更多