Author |
Topic |
|
ChemistryGuy
Australia
49 Posts |
Posted - 04/13/2022 : 8:12:31 PM
|
Origin Ver. and Service Release: OriginPro 2022 (64-bit) Beta5 Operating System: Windows 11
I am trying to export several graphs from an Origin project into a Word document, as embedded objects.
I managed to achieve this by activating the graph that I want to export, saving the Origin project, then running Word's "AddOLEObject" method on the Origin project. This is demonstrated in the code below.
However, the problem is that this is very slow. Specifically, it takes 15 - 20 seconds to embed each graph. I noticed that doing this manually from Origin (by right clicking on a graph, then clicking "Send to PowerPoint") takes less than a second.
Therefore I wanted to ask: Please would you advise me if there is a faster way to programmatically export graphs to Word as embedded objects?
import win32com.client as win32
import originpro as op
import time
src_opju = op.path('e')+ r'Samples\Map Data.opju'
op.open(file = src_opju, readonly = True)
word = win32.gencache.EnsureDispatch('Word.Application')
word_doc = word.Documents.Add()
gp = op.find_graph('Graph9')
gp.activate()
op.save("C:\\test\\test.opju")
tic = time.perf_counter()
word_doc.InlineShapes.AddOLEObject(ClassType := "Origin50.Graph", "C:\\test\\test.opju")
toc = time.perf_counter()
print(f"Adding embedded object took {toc - tic:0.4f} seconds")
word_doc.SaveAs2("C:\\test\\test.docx")
|
Edited by - ChemistryGuy on 04/13/2022 9:52:40 PM |
|
minimax
351 Posts |
Posted - 04/14/2022 : 06:07:27 AM
|
Hi ChemistryGuy,
Before we can look into the issue, would you mind to tell us what Python application you use to run the script?
PyCharm? or what else?
And what package you install for win32com.client? pypiwin32? or pywin32? |
|
|
ChemistryGuy
Australia
49 Posts |
Posted - 04/14/2022 : 06:42:32 AM
|
Hi Minimax,
Thank you for getting back to me, to answer your questions:
I am running the script using PyCharm.
I have installed the pywin32 package. However, if you think that a different package is better I am happy to install it. |
|
|
ChemistryGuy
Australia
49 Posts |
Posted - 04/14/2022 : 10:23:52 PM
|
By the way, there is one other issue with using the "AddOLEObject" method that I described above.
Each time it is called, several Origin background processes are generated. Consequently, when exporting multiple graphs, the maximum number of instances of Origin will be reached, and the import will fail because Origin cannot open.
I solved this problem by "killing" all Origin processes except the one that is running the Origin project that I wish to export from. This is illustrated in the code below.
I just wanted to mention this to make you aware of it, and in case it effects your recommendation for the best way of embedding the graphs.
import win32com.client as win32
import originpro as op
import psutil
import time
def add_Origin_to_Word(origin_graph, temp_proj, good_origin, word_doc):
origin_graph.activate()
op.save(temp_proj)
word_doc.InlineShapes.AddOLEObject(ClassType := "Origin50.Graph", FileName := temp_proj)
for proc in psutil.process_iter():
try:
# Get process name & pid from process object.
processName = proc.name()
processID = proc.pid
# Kill extra Origin processes (equivalent of Task Manager > End Task)
if "Origin" in processName and processID != good_origin:
proc.kill()
except:
pass
src_opju = op.path('e')+ r'Samples\Map Data.opju'
op.open(file = src_opju, readonly = True)
temp_proj_path = "C:\\test\\test.opju"
op.save(temp_proj_path)
for proc in psutil.process_iter():
try:
# Get process name & pid from process object.
processName = proc.name()
processID = proc.pid
if "Origin" in processName:
good_origin = processID
except:
pass
word = win32.gencache.EnsureDispatch('Word.Application')
word_doc = word.Documents.Add()
for origin_graph in op.graph_list("p"):
tic = time.perf_counter()
add_Origin_to_Word(origin_graph, temp_proj_path, good_origin, word_doc)
toc = time.perf_counter()
print(f"Adding embedded object took {toc - tic:0.4f} seconds")
word_doc.SaveAs2("C:\\test\\test.docx")
|
|
|
minimax
351 Posts |
Posted - 04/15/2022 : 02:08:59 AM
|
Hi ChemistryGuy,
Please try using CopyPage and PasteSpecial method instead, similar as how GUI manipulates.
It is fast here. (0.5739 seconds)
As to Origin background process, you need to call op.exit() explicitly to quit it.
import win32com.client as win32
from win32com.client import constants
import originpro as op
import time
src_opju = op.path('e')+ r'Samples\Map Data.opju'
op.open(file = src_opju, readonly = True)
word = win32.gencache.EnsureDispatch('Word.Application')
word_doc = word.Documents.Add()
gp = op.find_graph('Graph9')
gp.activate()
# 4 refers to OLE Object
# https://www.originlab.com/doc/COM/Classes/Application/CopyPage
op.po.CopyPage(gp.name,4)
tic = time.perf_counter()
word_doc.ActiveWindow.Selection.PasteSpecial(DataType=constants.wdPasteOLEObject)
toc = time.perf_counter()
print(f"Adding embedded object took {toc - tic:0.4f} seconds")
word_doc.SaveAs2("C:\\test\\test.docx")
op.exit()
|
|
|
ChemistryGuy
Australia
49 Posts |
Posted - 04/15/2022 : 9:25:24 PM
|
Thank you very much for this suggestion, it definitely made an improvement.
However, I have a follow up question. I used this approach to export multiple graphs. For the first graph it was very quick, however the subsequent graphs were much slower.
For example, the below code exports all graphs in the World project, and the output is shown below it. The first graph took only 0.4 seconds, but others took as long as 7.8 seconds.
I wondered whether this was because the clipboard held too much data, but I tried clearing this after each export, and it made no difference. Please would you advise me if you have any suggestion for how to avoid this slowdown?
import win32com.client as win32
from win32com.client import constants
import originpro as op
import time
from ctypes import windll
src_opju = op.path('e')+ r'Samples\Map Data.opju'
op.open(file = src_opju, readonly = True)
temp_proj_path = "C:\\test\\test.opju"
op.save(temp_proj_path)
word = win32.gencache.EnsureDispatch('Word.Application')
word_doc = word.Documents.Add()
i = 1
for origin_graph in op.graph_list("p"):
op.po.CopyPage(origin_graph.name, 4)
tic = time.perf_counter()
word_doc.ActiveWindow.Selection.PasteSpecial(DataType=constants.wdPasteOLEObject)
toc = time.perf_counter()
print(f"Adding embedded object took {toc - tic:0.4f} seconds")
if windll.user32.OpenClipboard(None):
windll.user32.EmptyClipboard()
windll.user32.CloseClipboard()
i = i + 1
word_doc.SaveAs2("C:\\test\\test.docx")
word_doc.Close()
word.Quit()
op.exit() Output: Adding embedded object took 0.3935 seconds Adding embedded object took 3.1253 seconds Adding embedded object took 7.5046 seconds Adding embedded object took 6.8718 seconds Adding embedded object took 3.1762 seconds Adding embedded object took 7.5270 seconds Adding embedded object took 3.1366 seconds Adding embedded object took 7.8283 seconds Adding embedded object took 6.6685 seconds |
|
|
minimax
351 Posts |
Posted - 04/18/2022 : 05:58:52 AM
|
Hi,
The calculated time includes PasteSpecial() function only.
We do not have ideas yet why the time varies.
OLE is not fast as far as we know. If you change to paste as picture only, each paste is indeed same fast.
PS, we realized that Origin provides an app "Send Graphs to Word". https://www.originlab.com/FileExchange/Details.aspx?fid=238
So you may even simply call it directly to do the job (the elapsed time is basically similar), like
import originpro as op
src_opju = op.path('e')+ r'Samples\Map Data.opju'
op.open(file = src_opju, readonly = True)
op.lt_exec(r'send_to_word mode:=2 output:="C:\test\test.docx";')
op.exit()
|
|
|
ChemistryGuy
Australia
49 Posts |
Posted - 04/18/2022 : 08:05:52 AM
|
Thank you for your reply, and for letting me know about the "Send Graphs to Word" app.
I tried installing the app and running your code, but as you said, the speed was similar to other methods. For example, exporting all 9 graphs from the World Map project took 49.8813 seconds.
As for exporting the graphs as images, this is what I have been doing so far and I agree that it is very fast. I was just hoping to import as OLE objects because this would make my program even more convenient for users.
I will keep importing the graphs as images for now. But if you come up with any ideas about how to speed up the OLE embed method, then I would greatly appreciate it and would be happy to test them out. |
Edited by - ChemistryGuy on 04/18/2022 08:22:58 AM |
|
|
|
Topic |
|
|
|