Insert image encoded in base 64 in a word document with python-docx? - postgresql

I use python-docx to generate word document. the user want that he create a template(in a field description) and when he write for example %(company_logo)s in the template, I replace this expression by the picture of the company that I recupered from the database.
as a first issue, I recupered the logo of a company from the database(Postgresql) and I use this code to replace this expression:
cr.execute("select name, logo_web from res_company where id=%s",[soc_id])
r=cr.fetchone()
if r :
company_name=r[0]
logo_company = r[1]
output = cStringIO.StringIO()
doc = docx.Document()
contenu=contenu % {'company_logo': logo_company, 'company_name': company_name,}
doc.add_paragraph(contenu)
The output was a document word that contains the base 64 code of the image as a string. I decoded this code and I tried to add it as a picture with the following code:
logo_company = base64.b64decode(r[1])
doc.add_picture(logo_company)
But I have this error that tells to me that argument must be the path to the picture.
TypeError: file() argument 1 must be encoded string without NULL bytes, not str

The documentation here explains that the add_picture() method takes a file as an argument. The file can be in the form of a path, or it can be a file-like object, such as an open file or a StringIO object. It cannot accept a bytestring containing the bytes of the image, which is what you've tried to do.
So you'll need to convert the image bytes into a file-like object, perhaps using StringIO(), and hand the resulting file-like object to add_picture(). That will get it working for you. Something like:
logo_file = StringIO(base64.b64decode(r[1]))
doc.add_picture(logo_file)

Related

How to return a bytes value in a cherry py request body

I have a postgres table that contains a bytea column. This column contains an image.
The SqlAlchemy model has this column defined as a LargeBinary. I've also tried to using BLOB, but It didn't change a thing.
I can easily retrieve a value from the database and what I get is a variable of type bytes.
How can I jsonify that bytes array? I need the json value so I can return it in the cherrypy request body like so :
data = { 'id_image': image.id_image, 'image': image.value }
I'm assuming you need to show that image in a browser or similar software.
Normally you can use Data URI when embedding image as a string into a web page. Modern browsers know how to decode it back.
Also I'm assuming you have a PNG image. If your case is different, feel free to change image/png to something, which matches your needs.
Here's how you can generate data URI using Python.
This example uses Python 3.6 syntax:
import base64
img_id = image.id_image
img_base64_encoded = base64.b64encode(image.value).decode('ascii')
img_type = 'image/png' # Use some smart image type guessing if applicable
img_data_uri = f'data:{img_type};base64,{img_base64_encoded}'
img_data = {
'id': image.id_image,
'data_uri': img_data_uri
}

how to read text files from content repository

My requirement is read text files from content repository in sap abap.I used SCMS_DOC_READ FM to read image file and creating url DP_CREATE_URL for creating image url but SCMS_DOC_READ not working for text.
Can any one suggest some code, FM or class .
There are two options based on your requirement:
Option 1: Use READ DATASET to read file.
DATA : FNAME(60) type c VALUE 'myfile.txt',
TEXT2(5) type c.
OPEN DATASET FNAME FOR INPUT IN TEXT MODE.
DO.
READ DATASET FNAME INTO TEXT2 LENGTH LENG.
WRITE: / SY-SUBRC, TEXT2.
IF SY-SUBRC <> 0.
EXIT.
ENDIF.
ENDDO.
CLOSE DATASET FNAME.
Option 2: Use Class CL_ABAP_CONV_IN_CE to read file.
Refer this tutorial page to get more information on this class.
You can easily find the answer there: http://scn.sap.com/thread/525075
If you want the short answer, you should use this(Note: I am not the author of this part):
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
FILENAME = "File path"
FILETYPE = 'ASC'
HAS_FIELD_SEPARATOR = 'X'
TABLES
DATA_TAB = IT.
Note : Internal table structure should be same as text File.

Why does Open XML API Import Text Formatted Column Cell Rows Differently For Every Row

I am working on an ingestion feature that will take a strongly formatted .xlsx file and import the records to a temp storage table and then process the rows to create db records.
One of the columns is strictly formatted as "Text" but it seems like the Open XML API handles the columns cells differently on a row-by-row basis. Some of the values while appearing to be numeric values are truly not (which is why we format the column as Text) -
some examples are "211377", "211727.01", "209395.388", "209395.435"
what these values represent is not important but what happens is that some values (using the Open XML API v2.5 library) will be read in properly as text whether retrieved from the Shared Strings collection or simply from InnerXML property while others get sucked in as numbers with what appears to be appended rounding or precision.
For example the "211377", "211727.01" and "209395.435" all come in exactly as they are in the spreadsheet but the "209395.388" value is being pulled in as "209395.38800000001" (there are others that this happens to as well).
There seems to be no rhyme or reason to which values get messed up and which ones which import fine. What is really frustrating is that if I use the native Import feature in SQL Server Management Studio and ingest the same spreadsheet to a temp table this does not happen - so how is that the SSMS import can handle these values as purely text for all rows but the Open XML API cannot.
To begin the answer you main problem seems to be values,
"209395.388" value is being pulled in as "209395.38800000001"
Yes in .xlsx file value is stored as 209395.38800000001 instead of 209395.388. And it's the correct format to store floating point numbers; nothing wrong in it. You van simply confirm it by following code snippet
string val = "209395.38800000001"; // <= What we extract from Open Xml
Console.WriteLine(double.Parse(val)); // < = Simply pass it to double and print
The output is :
209395.388 // <= yes the expected value
So there's nothing wrong in the value you extract from .xlsx using Open Xml SDK.
Now to cells, yes cell can have verity of formats. Numbers, text, boleans or shared string text. And you can styles to a cell which would format your string to a desired output in Excel. (Ex - Date Time format, Forced strings etc.). And this the way Excel handle the vast verity of data. It need this kind of formatting and .xlsx file format had to be little complex to support all.
My advice is to use a proper parse method set at extracted values to identify what format it represent (For example to determine whether its a number or a text) and apply what type of parse.
ex : -
string val = "209395.38800000001";
Console.WriteLine(float.Parse(val)); // <= Float parse will be deduce a different value ; 209395.4
Update :
Here's how value is saved in internal XML
Try for yourself ;
Make an .xlsx file with value 209395.388 -> Change extention to .zip -> Unzip it -> goto worksheet folder -> open Sheet1
You will notice that value is stored as 209395.38800000001 as scene in attached image.. So nothing wrong on API for extracting stored number. It's your duty to decide what format to apply.
But if you make the whole column Text before adding data, you will see that .xlsx hold data as it is; simply said as string.

Issues when reading a .nc file

I got this .nc file. However, when I read the file like this
ncid = netcdf.open(ncfile)
It gives me only a number. It was supposed to contain some data. I am not sure what's wrong with it. Can anyone please provide some information?
According to the documentation, netcdf.open only returns the NetCDF ID, not the data:
ncid = netcdf.open(source) opens source, which can be the name of a
NetCDF file or the URL of an OPeNDAP NetCDF data source, for read-only
access. Returns a NetCDF ID in ncid.
You probably want to use ncread.
Note:
ncid = netcdf.open(ncfile)
Where ncid is a netCDF file identifier returned by netcdf.create or
netcdf.open.
Eg : In your Case
ncid=netcdf.open(ncfile,'NC_NOWRITE');
varidp=netcdf.inqVarID(ncid,'varname'); //returns varid
Eg : Official
This example opens the example netCDF file included with MATLABĀ®, example.nc, and uses several inquiry functions to get the ID of the first variable.
ncid = netcdf.open('example.nc','NC_NOWRITE');
% Get information about first variable in the file.
[varname, xtype, dimids, atts] = netcdf.inqVar(ncid,0);
% Get variable ID of the first variable, given its name
varid = netcdf.inqVarID(ncid,varname)
Ref:http://www.mathworks.in/help/matlab/ref/netcdf.inqvarid.html
Thanks

How To Send a PDF File to a Progress AppServer?

I have a PDF file at client and i want to send this PDF file on AppServer. How can i send this pdf file at AppServer?
define temp-table ttFileList no-undo
field file-id as integer
field file-content as blob.
create ttFileList.
assign ttFileList.file-id = 1.
copy-lob from file("pdffilename") to ttFileList.file-content.
run DoSomethingWithAPDF on hAppServer
( input table ttFileList ).
This depends on the version of progress you are using, if you are using v9 then you will need to use small chunks of raw data streamed in segments. With OpenEdge (might have been 10.1B) we got CLOB and BLOB support, you can create a procedure which takes a temp-table as an argument.
It also depends on your calling language. For .NET and Java this will get translated into a byte array.
For your app-server create a procedure similar to the following:
def temp-table ObjectTransfer no-undo
field Code as char
field Number as int
field DataContent as blob
field MimeType as char.
procedure AddObjectData:
def input param table for ObjectTransfer.
def var k as int no-undo.
for each ObjectTransfer:
find last ObjectTable no-lock
where ObjectTable.Code = ObjectTransfer.Code
no-error.
if avail ObjectTable then
k = ObjectTable.Number + 1.
else
k = 1.
create ObjectTable.
assign
ObjectTable.Code = ObjectTransfer.Code
ObjectTable.Number = k
ObjectTable.MimeType = ObjectTransfer.MimeType
ObjectTable.DataContent = ObjectTransfer.DataContent
.
end.
end procedure.
Generate proxies, you will now call this from .NET and Java using a simple byte array as an input temp-table data-type.
Use raw datatype, you might need to send the file in chunks. Another alternative is to use character+BASE64.