Как извлечь объекты OLE из таблицы Excel, используя Python? - PullRequest
0 голосов
/ 19 января 2020

Я хотел бы использовать Python для извлечения OLE-объектов из таблицы Excel в буфер обмена Windows.

Этот пост больше не помог, поскольку он предназначен для VBA. И этот пост по-прежнему остается без ответа.

Предполагается, что данная таблица Excel (с объектами OLE ChemDraw или ChemSketch):

enter image description here

Существует несколько модулей Python, которые могут обрабатывать файлы Excel, например, openpyxl, xlrd. Модуль win32clipboard может помещать данные в буфер обмена.

Мои проблемы:

  1. Я не вижу, как получить внедренный объект OLE в буфер обмена. Возможно, openpyxl и xlrd вместе с win32clipboard не подходят для этого?
  2. Есть Python модуль oletools, который может это сделать, но я не понимаю, как он работает , https://pypi.org/project/oletools/

С этой страницы:

oleobj: для извлечения встроенных объектов из файлов OLE.

Кажется, это именно то, что я ищу, однако я не смог найти MCVE. И, к сожалению, документация oleobj в основном сводится к: «прочитай исходный код и узнай сам». Буду благодарен за подсказки и помощь.

Мой код пока:

### trying to extract OLE objects from Excel table into clipboard
from openpyxl import load_workbook
import win32clipboard as clpbd

def set_clipboard(data):
    clpbd.OpenClipboard()
    clpbd.EmptyClipboard()
    clpbd.SetClipboardText(data)    # I'm aware, this is only for text, is there anything for OLEs?
    clpbd.CloseClipboard()

def print_clipboard():
    clpbd.OpenClipboard()
    data = clpbd.GetClipboardData()
    clpbd.CloseClipboard()
    print(data)

wb = load_workbook(filename = 'tbChemOLE.xlsx')
ws = wb.active

myName = ws['A3'].value    # result: napthalene
myImage = ws['B3'].value   # result: None
myObject = ws['C3'].value  # result: None

set_clipboard(myName)
print_clipboard()          # result: Naphtalene
# set_clipboard(myImage)   # crash, because myImage is None
print_clipboard()     
# set_clipboard(myObject)  # crash, because myObject is None
print_clipboard()        

wb.close()
### end of code

1 Ответ

0 голосов
/ 20 января 2020

Тем временем я нашел этот пост , где ОП фактически не хотел, чтобы объекты OLE находились в буфере обмена, но для меня это нормально. На самом деле, нет необходимости в openpyxl или xlrd, но win32com.client требуется.

Я могу получить все объекты OLE, однако они индексируются (вероятно) в последовательности их добавления. Поэтому мне нужно создать словарь с индексом строки в качестве ключа и набором индекса объекта OLE и именем в качестве значения.

Код:

### copy OLE object in certain cell to clipboard
import win32com.client as win32
import win32clipboard

excel = win32.gencache.EnsureDispatch('Excel.Application')
ffname = r'C:\Test\tbChemOLE.xlsx'
wb = excel.Workbooks.Open(ffname)
ws = wb.Worksheets.Item(1)
objs = ws.OLEObjects()

def get_all_OLEs():
    oleNo_dict = {}     # dictionary for all OLE objects
    for i in range(1,len(objs)+1):    # loop all OLE objects
        obj = objs.Item(i) 
        myRow = obj.TopLeftCell.Row        # row of OLE object
        myName = ws.Cells(myRow,1).Value   # corresponding name
        oleNo_dict[myRow] = (i, myName)
    return oleNo_dict

def get_OLE(row):
    try: 
        objs[oleNo_dict[row][0]].Copy()
        win32clipboard.OpenClipboard()
        data = win32clipboard.GetClipboardData(0xC004) # Binary access
        win32clipboard.CloseClipboard()
    except Exception as e:
        print(e)
        win32clipboard.OpenClipboard()
        win32clipboard.EmptyClipboard()
        win32clipboard.CloseClipboard()
    return oleNo_dict[row]
    # and OLE is on clipboard if found

oleNo_dict = get_all_OLEs()

row = 4
myMolecule = get_OLE(row)
print(myMolecule[1], "OLE object is now on the clipboard.")

wb.Close()
excel.Application.Quit()
### end of code

Результат:

Anthracene OLE object is now on the clipboard.
...