Python3 Win32com Copy body of an email and paste to a new excel file - email

I'm trying to copy paste an html table received by outlook email to a new excel spreadsheet but I get a "pywintypes.com_error." Seeking a more pythonic way to do a the equivalent of a "Control+A" on an email body and paste to a new spreadsheet.
The relevant pieces of code are:
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
# Select main Inbox
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
try:
for message in messages:
try:
if message.subject == 'myemailed Report':
print('Sender:' , message.sender)
print(message.subject)
mailItem = message.HTMLBody # <----Attempting to copy the body of the selected email.
# Start an instance of Excel
Xlsx = win32com.client.Dispatch("Excel.Application")
# Prevent Excel from asking questions.
Xlsx.DisplayAlerts = True # will change to False
Xlsx.Visible = True # will change to False
# Create a new Excel Workbook
workbook = Xlsx.Workbooks.Add()
ws = workbook.Sheets("Sheet1")
ws.Range('a7').select
ws.Paste(mailItem) # <--------------- Generates Error
workbook.SaveAs(mydesktop+'UpdatedSheet.xlsx')
# Quit Excel
Xlsx.Quit()
except:
x=1
except:
x=1
I get a message: Traceback (most recent call last):
File "", line 1, in
ws.Paste(mailItem)
File ">", line 3, in Paste
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'Paste method of Worksheet class failed', 'xlmain11.chm', 0, -2146827284), None)
Is there a better way? Help is appreciated!

ws.Paste(mailItem) is the main part of the problem. Code should be:
ws.Paste()
However - copying the email body as if hitting "Ctrl-A" is a little more involved and there are a lot of almost answers. I managed to get the following work but I don't know why it works.
I used import pyperclip which requires pip install pyperclip, along with the following code:
import pyperclip
def copy(text):
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(text, win32clipboard.CF_UNICODETEXT)
win32clipboard.CloseClipboard()
def paste():
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)
win32clipboard.CloseClipboard()
return data
Then later on...
mailItem = message.HTMLBody
pyperclip.copy(mailItem)
# Start an instance of Excel
Xlsx = win32com.client.Dispatch("Excel.Application")
# Create a new Excel Workbook
workbook = Xlsx.Workbooks.Add()
ws = workbook.Sheets("Sheet1")
ws.Range('a1').select
ws.Paste()
ws.Range('a1').select
workbook.SaveAs(myexcel.xlsx')
I tried doing this without using pyperclip but the combination of the two def's in the beginning and the ws.Paste() worked.

Related

Adjust wait_time in locust using custom arguments via CLI

I want to adjust wait_time parameter by passing it via CLI.
I have tried the following way:
custom_wait_time = None
# Add custom argument to locust
#events.init_command_line_parser.add_listener
def init_parser(parser):
parser.add_argument("--locust-wait-time",
type=int,
include_in_web_ui=True,
default=None,
help="Wait time per each request of a user.")
#events.init.add_listener
def _(environment, **kwargs):
global custom_wait_time
custom_wait_time = int(environment.parsed_options.locust_wait_time)
print(custom_wait_time) # First print
class MyUser(HttpUser):
global custom_wait_time
print(custom_wait_time) # Second print
wait_time = constant(custom_wait_time)
Assume that custom_wait_time=10 when I pass it via CLI, the First print gives me custom_wait_time=10 while the Second print gives me custom_wait_time=None instead of 10, so the wait_time = constant(custom_wait_time) will break and give me the error below:
Traceback (most recent call last):
File "src/gevent/greenlet.py", line 908, in gevent._gevent_cgreenlet.Greenlet.run
File "/Users/opt/anaconda3/envs/ai/lib/python3.7/site-packages/locust/user/users.py", line 176, in run_user
user.run()
File "/Users/opt/anaconda3/envs/ai/lib/python3.7/site-packages/locust/user/users.py", line 144, in run
self._taskset_instance.run()
File "/Users/opt/anaconda3/envs/ai/lib/python3.7/site-packages/locust/user/task.py", line 367, in run
self.wait()
File "/Users/opt/anaconda3/envs/ai/lib/python3.7/site-packages/locust/user/task.py", line 445, in wait
self._sleep(self.wait_time())
File "/Users/opt/anaconda3/envs/ai/lib/python3.7/site-packages/locust/user/task.py", line 451, in _sleep
gevent.sleep(seconds)
File "/Users/opt/anaconda3/envs/ai/lib/python3.7/site-packages/gevent/hub.py", line 157, in sleep
if seconds <= 0:
TypeError: '<=' not supported between instances of 'NoneType' and 'int'
Any help would be appreciated.
The problem is that the code will run in the wrong order - MyUser is defined before any of the init-methods are called.
If you instead do MyUser.wait_time = constant(custom_wait_time) inside your init handler (and dont set it at all in the class) it should work.
That way you dont need any globals either :)
I've just do the same work.
#events.init_command_line_parser.add_listener
def _(parser):
parser.add_argument("--waitTime", type=float, env_var="LOCUST_WAIT_TIME", default=1.0, help="wait time between each task of an user")
# Set `include_in_web_ui` to False if you want to hide from the web UI
#parser.add_argument("--my-ui-invisible-argument", include_in_web_ui=False, default="I am invisible")
and in the test class, just use it value like this
class GetInfoUser(HttpUser):
def wait_time(self):
return self.environment.parsed_options.waitTime

Libre office configuration file bootstrap.ini corrupt

I am using the libreoffice-convert package to convert a Word file into PDF. But when I try to convert I get this error. How do I fix this? I have installed LibreOffice 7.0.5
Console log is showing this error:
'C:\\Program Files\\LibreOffice\\program\\soffice.exe -env:UserInstallation=file://C:\\Users\\thesa\\AppData\\Local\\Temp\\soffice-10416-bQefydwUfs2F --headless --convert-to .pdf --outdir C:\\Users\\thesa\\AppData\\Local\\Temp\\libreofficeConvert_-10416-v46bO7ljGHRe C:\\Users\\thesa\\AppData\\Local\\Temp\\libreofficeConvert_-10416-v46bO7ljGHRe\\source'
Try this, you will probably need administrator rights.
Locate and copy your orignal file, for example to "bootstrap.ini.org", in the same directory1.
Open the file and replace its contents with this, which is a copy of my file:
[Bootstrap]
InstallMode=<installmode>
ProductKey=LibreOffice 7.0
UserInstallation=$SYSUSERCONFIG/LibreOffice/4
Another option is to re-install or repair the installation.
Note 1: This copy is just in case you need to revert.
//let data = await fs.promises.readFile(path_to_excel_file);
let data = fs.readFileSync(path_to_excel_file)
let pdfFile = await libreConvert(data, '.pdf', undefined);
await fs.promises.writeFile(`${__dirname}/${docName}.pdf`, pdfFile);
res.download(`${__dirname}/${docName}.pdf`)
It will works File.
Even If don't work then follow
below step:
Add this line 14 after instalDir
const installDir = tmp.dirSync({prefix: 'soffice', unsafeCleanup: true, ...tmpOptions});
const posixInstallDir = installDir.name.split(path.sep).join(path.posix.sep);
then Replace commant
let command = `${results.soffice} --headless --convert-to ${format}`;
That's it..
-env:UserInstallation needs to be in URI form.
Note: also that you using file:// this should be file:/// see File URI scheme
-env:UserInstallation=file:///C:/Users/thesa/AppData/Local/Temp/soffice-10416-bQefydwUfs2F
>>> from pathlib import Path
>>> def get_posix(mypath) -> str:
>>> p = Path(mypath)
>>> return p.as_posix()
>>> tmp = "C:\\Users\\thesa\\AppData\\Local\\Temp\\soffice-10416-bQefydwUfs2F"
>>> get_posix(tmp)
'C:/Users/thesa/AppData/Local/Temp/soffice-10416-bQefydwUfs2F'
or
>>> from pathlib import Path
>>> tmp = Path("C:\\Users\\thesa\\AppData\\Local\\Temp\\soffice-10416-bQefydwUfs2F")
>>> tmp.as_uri()
'file:///C:/Users/thesa/AppData/Local/Temp/soffice-10416-bQefydwUfs2F'

AttributeError on Oandapy API

I'm trying to do "100 lines of python code" for algorithmic trading and have been stopped early in my tracks with an attribute error.
I'm using sublime text and running it on python 3.7.
Here is the code I used:
import configparser
import oandapy as opy
config = configparser.ConfigParser()
config.read("oanda.cfg")
oanda = opy.API(environment = "practice",
access_token = config["oanda"] ["access_token"] )
Here are the results:
Traceback (most recent call last):
File "100lines.py", line 7, in <module>
oanda = opy.API(environment = "practice",
AttributeError: module 'oandapy' has no attribute 'API'
Try this:
# Print all attributes/functions in module
print(dir(opy))
and check the modules present
I think you'll have to use 'APIv20' rather than just 'API'
The api method is now called APIv20 in the current version (0.0.9).
so changing the last line to:
oanda = opy.APIv20(environment='practice', access_token=config['oanda']['access_token'])
will make solve your issue.

Save a file in a flask-wtf form to MongoDB's GridFS

I'm using the flask-user extension (https://flask-user.readthedocs.io/) along with the mongoengine adapter and flask-wtf to create an HTML form that'll accept several files (images, mp4). The goal is to directly store those files in MongoDB using GridFS but I can't get it to work without storing the image locally on the flask server first...
Here's my non-working code:
#bp.route('/video1', methods=['GET', 'POST'])
#login_required
def video1():
video1Form = Video1Form()
if request.method == 'POST' and video1Form.validate_on_submit():
newVideo1 = Video1(
slogan = video1Form.slogan.data,
objectif = video1Form.objectif.data,
stat1 = video1Form.stat1.data,
stat2 = video1Form.stat2.data
)
name = secure_filename(str(current_user.id) + "__" + "logo.png")
fh = open(video1Form.logo.data, 'rb')
newVideo1.logo.put(fh, filename=name, content_type = "image/jpeg")
newVideo1.save()
return redirect(url_for('video.download'))
if video1Form.errors:
flash(video1Form.errors, 'alert-danger')
return render_template('video/video1.html', video1Form=video1Form)
`
I get the following error on:
[...]File "/home/lucaspierru/Documents/IKADA/sos_sponsors/app/video/routes.py", line 35, in video1
fh = open(video1Form.logo.data, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: 'name_of_the_uploaded_file.ext'
Is it possible to point directly to the file's content and not just get the filename without saving it to the server first ?
I found my mistake:
I forgot to add the enctype="multipart/form-data" attribute to my HTML <form> tag and apparently it is needed to properly upload files, otherwise they'll be considered as text data.

An error in my code to be a simple ftp

I met an error when running codes at the bottom. It's like a simple ftp.
I use python2.6.6 and CentOS release 6.8
In most linux server, it gets right results like this:(I'm very sorry that I have just sign up and couldn't )
Clinet:
[root#Test ftp]# python client.py
path:put|/home/aaa.txt
Server:
[root#Test ftp]# python server.py
connected...
pre_data:put|aaa.txt|4
cmd: put
file_name: aaa.txt
file_size: 4
upload successed.
But I get errors in some server(such as my own VM in my PC). I have done lots of tests(python2.6/python2.7, Centos6.5/Centos6.7) and found this error is not because them. Here is the error imformation:
[root#Lewis-VM ftp]# python server.py
connected...
pre_data:put|aaa.txt|7sdfsdf ###Here gets the wrong result, "sdfsdf" is the content of /home/aaa.txt and it shouldn't be sent here to 'file_size' and so it cause the "ValueError" below
cmd: put
file_name: aaa.txt
file_size: 7sdfsdf
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 10699)
Traceback (most recent call last):
File "/usr/lib64/python2.6/SocketServer.py", line 570, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib64/python2.6/SocketServer.py", line 332, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib64/python2.6/SocketServer.py", line 627, in __init__
self.handle()
File "server.py", line 30, in handle
if int(file_size)>recv_size:
ValueError: invalid literal for int() with base 10: '7sdfsdf\n'
What's more, I found that if I insert a time.sleep(1) between sk.send(cmd+"|"+file_name+'|'+str(file_size)) and sk.send(data) in client.py, the error will disappear. I have said that I did tests in different system and python versions and the error is not because them. So I guess that is it because of some system configs? I have check about socket.send() and socket.recv() in python.org but fount nothing helpful. So could somebody help me to explain why this happend?
The code are here:
#!/usr/bin/env python
#coding:utf-8
################
#This is server#
################
import SocketServer
import os
class MyServer(SocketServer.BaseRequestHandler):
def handle(self):
base_path = '/home/ftp/file'
conn = self.request
print 'connected...'
while True:
#####receive pre_data: we should get data like 'put|/home/aaa|7'
pre_data = conn.recv(1024)
print 'pre_data:' + pre_data
cmd,file_name,file_size = pre_data.split('|')
print 'cmd: ' + cmd
print 'file_name: '+ file_name
print 'file_size: '+ file_size
recv_size = 0
file_dir = os.path.join(base_path,file_name)
f = file(file_dir,'wb')
Flag = True
####receive 1024bytes each time
while Flag:
if int(file_size)>recv_size:
data = conn.recv(1024)
recv_size+=len(data)
else:
recv_size = 0
Flag = False
continue
f.write(data)
print 'upload successed.'
f.close()
instance = SocketServer.ThreadingTCPServer(('127.0.0.1',9999),MyServer)
instance.serve_forever()
#!/usr/bin/env python
#coding:utf-8
################
#This is client#
################
import socket
import sys
import os
ip_port = ('127.0.0.1',9999)
sk = socket.socket()
sk.connect(ip_port)
while True:
input = raw_input('path:')
#####we should input like 'put|/home/aaa.txt'
cmd,path = input.split('|')
file_name = os.path.basename(path)
file_size=os.stat(path).st_size
sk.send(cmd+"|"+file_name+'|'+str(file_size))
send_size = 0
f= file(path,'rb')
Flag = True
#####read 1024 bytes and send it to server each time
while Flag:
if send_size + 1024 >file_size:
data = f.read(file_size-send_size)
Flag = False
else:
data = f.read(1024)
send_size+=1024
sk.send(data)
f.close()
sk.close()
The TCP is a stream of data. That is the problem. TCP do not need to keep message boundaries. So when a client calls something like
connection.send("0123456789")
connection.send("ABCDEFGHIJ")
then a naive server like
while True;
data = conn.recv(1024)
print data + "_"
may print any of:
0123456789_ABCDEFGHIJ_
0123456789ABCDEFGHIJ_
0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F_G_H_I_J_
The server has no chance to recognize how many sends client called because the TCP stack at client side just inserted data to a stream and the server must be able to process the data received in different number of buffers than the client used.
Your server must contain a logic to separate the header and the data. All of application protocols based on TCP use a mechanism to identify application level boundaries. For example HTTP separates headers and body by an empty line and it informs about the body length in a separate header.
Your program works correctly when server receives a header with the command, name and size in a separate buffer it it fails when client is fast enough and push the data into stream quickly and the server reads header and data in one chunk.