Comment générer des fichiers Excel et Pdf ?
Je souhaite créer des fichiers excel (xls) et des fichiers pdf pour la création de rapports.
Ces rapports étant complexes je souhaite programmer en objectscript leur création et non utiliser un système de report.
Je cherche les classes qui pourraient m'aider à réaliser cette tâche sachant que pour moi ces classes doivent exister puisqu'Iris propose la génération de fichiers xls.
J'avais demandé à chatGpt qui m'a "inventé" une classe inexistante : %Library.Excel.Workbook qui correspondait tout a fait à ce que je cherche.
Mes questions sont donc :
Existe-t-il une ou des classes permettant la génération de fichiers xls et pdf ?
Quelle approche serait la meilleure selon vous si ce n'est pas le cas ? librairie externe ?, script externe ?
Comments
Bonjour,
La facon, la plus simple aujourd'hui est de passer par du code Python ou Java pour ce genre d'opération :
- Java :
- Python :
Ou encore utiliser le super module d'interopérabilité 100% python :
Bonjour Guillaume,
Merci pour cette réponse rapide, j'utilise actuellement Iris en objectscript uniquement, donc je ne suis pas trop à l'aise avec l'intégration de python.
Je dois avoir prochainement une présentation/formation à l'intégration de python (langage que je pratique un peu par ailleurs) par @Sylvain Guilbaud
Afin de rendre cette session plus productive j'aimerai bien me dégrossir un peu sur le sujet, quelles ressources pourrais-tu me conseiller ?
Les bons sites pour commencer à apprendre le python sont :
Ensuite, je m'inspirerai des examples cités dans la réponse précédente.
Un article dédié sur Python et IRIS doit sortir pour l'année prochain, il présentera les similitudes (qui sont nombreuses) et aussi les différences entre l'ObjectScript et le Python.
Patience :)
Merci pour ces liens, mais en fait je me dbrouille avec python, c'était bien sur l'intégration de Python dans Iris que je m'interrogeais (j'ai cru comprendre que l'on peut utiliser python en embarqué ou indépendamment d'Iris.
J'attendrai l'article dont tu me parles ;-) et verrai cela avec @Sylvain Guilbaud bientôt
Bonnes fêtes et merci pour tes réponses
Bonjour @Pierre LaFay
en m'inspirant des liens proposés par @Guillaume Rongier tu trouveras ci-dessous et en ligne un exemple de génération de feuille Excel à partir de openpyxl
Code
/// d ##class(apptools.python.xlsx).test()Class apptools.python.xlsx
{
Parameter DATADIRECTORY = "/home/irisowner/dev/data/";/// d ##class(apptools.python.xlsx).test()ClassMethod test(name As%String = "titanicTest") As%Status
{
set name=name_$INCREMENT(^RunAppTest(name))
set sql="select * FROM dc_demo.titanic"
#; set sql="select name,sex,age FROM dc_demo.titanic"set gn="^||tmp",format=",n,n,n,n,s5,s5,s40,s5,s50"set format("freeze")="B3";freezeset format("title")="Title "_sql
set format("sheetname")="test"
#; do ##class(apptools.core.sys).SaveSQL(sql,gn)set exec="##class(apptools.python.xlsx).MarkRed(.%AppLogInfoVal, .%AppLogInfoCol, .%AppLogInfoHead, .%AppLogInfoTemp)"
#; do ##class(apptools.python.xlsx).gn2xlsx(gn,.format,..#DATADIRECTORY_"___gn2xlsx*.xlsx","Title "_sql,,,,exec)set format("freeze")="B4";freezedo##class(apptools.python.xlsx).sql2xlsx(sql,.format,..#DATADIRECTORY_name_".xlsx")
do..toPDF(name)
return$$$OK
}
ClassMethod sql2xlsx(sql, format = "", file As%String = "/home/irisowner/dev/data/sample-py-*.xlsx", title = "")
{
set st=$$$OKset statement = ##CLASS(%SQL.Statement).%New()
set status=statement.%Prepare(sql)
if$$$ISERR(status) {write"%Prepare failed:"do$SYSTEM.Status.DisplayError(status) quit}
set rset=statement.%Execute()
if (rset.%SQLCODE '= 0) {write"%Execute failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Messagequit}
;prepare XLSXtry {
set openpyxl = ##class(%SYS.Python).Import("openpyxl")
} catch err {
do..InstallPy("openpyxl")
set openpyxl = ##class(%SYS.Python).Import("openpyxl")
}
set wb = openpyxl.Workbook()
#; grab the active worksheetset ws = wb.active
set ws.title = $select($D(format("sheetname"),ds):ds,1:"sheetname")
set pybuiltins = $system.Python.Import("builtins")
set pycols = pybuiltins.list()
do pycols.append(" ")
do ws.append(pycols)
set pycols = pybuiltins.list()
set (count)=0set ColCount=statement.%Metadata.columns.Count()
for i=1:1:ColCount {
do pycols.append(statement.%Metadata.columns.GetAt(i).colName)
set col=openpyxl.utils."get_column_letter"(i)
}
do ws.append(pycols)
while (rset.%Next()) {
set count=count+1set pyrows = pybuiltins.list()
for ii=1:1:ColCount {
set val=..CleanCtrl(rset.%GetData(ii))
if$e($P(format,",",ii),1)="d" { //dateset val=..ToPyDate(val)
}
elseif$e($P(format,",",ii),1,2)="dt" { //datetimeset val=..ToPyDateTime(val)
}
elseif$e($P(format,",",ii),1)="n" { //numberset val=+val
}
do pyrows.append(val)
}
do ws.append(pyrows)
}
;}if$g(format("freeze"))'="" {
; set builtins = $system.Python.Import("builtins") zwrite builtins.type(ws) zwrite builtins.dir(wb)set ws."freeze_panes" = pybuiltins.str(format("freeze")) ;format("freeze");set ws."freeze_panes" = "B2" ;format("freeze")
}
else {
set ws."freeze_panes" = pybuiltins.str("B2") ;default
}
if file["*"set file=$replace(file,"*","-"_$zd($h,3)_"_"_$tr($zt($p($h,",",2),1),":"))
write !,"Save into "_file_" rows: "_count
do wb.save(file)
return$GET(count)
}
ClassMethod toPDF(file As%String) As%Status [ Language = python ]
{
import pandas as pd
from csv2pdf import convert
PATH = '/home/irisowner/dev/data/'
PATH_TO_XLSX = PATH+file+'.xlsx'
PATH_TO_CSV = PATH+file+'.csv'
PATH_TO_PDF = PATH+file+'.pdf'
read_file = pd.read_excel (PATH_TO_XLSX)
read_file.to_csv (PATH_TO_CSV, index = None, header=True)
convert(PATH_TO_CSV , PATH_TO_PDF)
}
/// set gn="^||tmp",format="n,s150,,,,,,,,d," /// set format("freeze")="B5" ;freeze/// d ##class(apptools.core.sys).SaveSQL("select * from apptools_core.Log order by id desc",gn)/// d ##class(apptools.python.xlsx).gn2xlsx(gn,.format,"/iris-backup/temp/test*.xlsx","Test")/// Example coloring a column values if is not null/// set exec="##class(apptools.python.xlsx).MarkRed(.%AppLogInfoVal, %AppLogInfoCol, %AppLogInfoHead, .%AppLogInfoTemp)"ClassMethod MarkRed(Val, Col, Head, openpyxl)
{
s res=Val
if$g(Head) {
if res.value="DispatchClass"set Col("DispatchClass",Col)=""
}
else {
if$Data(Col("DispatchClass",Col)) {
if res.value'="" {
;set argsfill = {"start_color":"D3D3D3", "end_color":"D3D3D3", "fill_type":"solid"};set fill = openpyxl.styles.PatternFill(argsfill...) set argsfont = {"color":"DC143C", "bold":true, "italic":false, "size":11} ;color Crimsonset font = openpyxl.styles.Font(argsfont...)
;set res.value=$FN(res.value,"",2);set res.fill=fillset res.font=font
}
}
}
q res
}
/// do ##class(apptools.python.xlsx).InstallPy("openpyxl")ClassMethod InstallPy(lib)
{
// depricated ;set sc = ##class(%SYS.Python).Install("openpyxl")set cmd="pip3 install --target /usr/irissys/mgr/python/ "_lib
if$zversion(1)'=3 {
set tMgrDir = $System.Util.ManagerDirectory()
set tBinDir = $System.Util.BinaryDirectory()_"irispip.exe"set cmd=tBinDir_" install --target "_tMgrDir_"python "_lib
}
set st=##class(%ZPM.PackageManager.Developer.Utils).RunCommandViaZF(cmd,.tLog,.tErr)
quit$$$OK
}
/// Date YYYY-MM-DD HH:MM:SS to Python dt.datetimeClassMethod ToPyDateTime(val, ByRef dt)
{
quit:'val val
if val["."set val=$p(val,".",3)_"-"_$p(val,".",2)_"-"_$p(val,".",1) // format YYYY-MM-DDif val'["-"set val=$zd(+val,3) // $h formatset dt = ##class(%SYS.Python).Import("datetime")
set val=dt.datetime(+$p(val,"-",1), +$p(val,"-",2), +$p($p(val,"-",3)," "),+$p($p(val,":",1)," ",2),+$p($p(val,":",2)," ",2),+$p($p(val,":",3)," ",2))
quit val
}
/// Date YYYY-MM-DD to Python dt.dateClassMethod ToPyDate(val, ByRef dt)
{
quit:'val val
if val["."set val=$p(val,".",3)_"-"_$p(val,".",2)_"-"_$p(val,".",1) // format YYYY-MM-DDif val'["-"w111_val_111 set val=$zd(+val,3) // $h formatset dt = ##class(%SYS.Python).Import("datetime")
set val=dt.date(+$p(val,"-",1), +$p(val,"-",2), +$p($p(val,"-",3)," "))
quit val
}
ClassMethod CleanCtrl(val)
{
quit$zstrip(val,"*C")
}
}
Une fois obtenu le fichier Excel, il est possible de le convertir en CSV puis en PDF en utilisant les librairies pandas et csv2pdf
ClassMethod toPDF(file As%String) As%Status [ Language = python ]
{
import pandas as pd
from csv2pdf import convert
PATH = '/home/irisowner/dev/data/'
PATH_TO_XLSX = PATH+file+'.xlsx'
PATH_TO_CSV = PATH+file+'.csv'
PATH_TO_PDF = PATH+file+'.pdf'
read_file = pd.read_excel (PATH_TO_XLSX)
read_file.to_csv (PATH_TO_CSV, index = None, header=True)
convert(PATH_TO_CSV , PATH_TO_PDF)
}