Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Salut à tous,
me revoici sur le forum pour une nouvelle question concernant cette fois ci l'export d'une datawindow vers excel...
En effet, je dois réaliser une edition de mon écran (prévision de trésorerie) sous excel et on me demande d'exporter ce qui est affiché à l'écran avec bien sûr la même mise en forme.
L'ecran en question est le suivant pour avoir une idée :
Ce que j'affiche à l'écran dans ma datawindow, soit les entetes de colonnes (les dates) ainsi que le contenu de ma datawindow est dynamique et résulte d'une part des choix établis avec les cases a cocher affichées au dessus de la DW et d'un traitement pour effectuer la mise en forme de ma DW (affichage pertinent pour l'utilisateur, couleur, gras, etc...).
Bref, j'avais commencé à regarder la fonction saveas avec le param excel5! ou excel8! mais le probleme c'est que je ne retrouve que des données brute avec toutes les colonnes issu du painter de la DW, avec les noms des entetes de colonnes correspondant aux DBName des champs dans le painter et non pas ce que j'ai à l'écran, pas de séparateur de lignes, de couleurs, de gras etc ...
Moi je veux la même DW à l'écran dans EXCEL (même mise en forme, colonnes affichées et données intégrées of course !).
J'ai testé une librairie DW2xls (.pbd accompagné d'une DLL) à incorporer dans le target du workspace. Celle-ci ne me satisfait qu'a moitié dans la mesure où :
1. Ca ne passe pas tout le temps sans un message d'avertissement ou d'erreur (non debuggable forcement) lors de l'utilisation de la fonction d'import vers excel
2. Cette librairie est payante pour son utilisation (54€ je crois)...
Hormis ceci elle ne bosse pas trop mal cette fonction et respecte bien mes criteres de mise en forme (mais pas sans petits plantage ce qui ne peut en aucun cas suffire à la demande de nos clients !!!)
Quelqu'un aurait une astuce ou un bout de code qui saurait faire ceci ????
D'avance un grand merci.
FmxStyle
Dernière modification par fmxstyle (27-08-2007 16:39:43)
Hors ligne
2) 54€ c'est le prix d'une heure de prestation. Enorme en effet
Qu'est ce que tu as comme erreurs avec DW2xls ?
1) Tu l'enregistre au format html et tu force Excel à l'ouvrir (via OLE)
Depuis http://tech.groups.yahoo.com/group/Powe … werScript/ :
/////////////////////////////////////////////////////////////////////////////////////////////////////// // Converting DataWindow to Excel file /////////////////////////////////////////////////////////////////////////////////////////////////////// // Export DataWindow to Excel including computed-columns, headers, footers, groups, text labels, etc... /////////////////////////////////////////////////////////////////////////////////////////////////////// // ... Init docname // ... GetFileOpenName or any other method // IF dw.SaveAs( docname, HTMLTable!, TRUE ) = -1 THEN MessageBox("Warning", "Unable to export data. Error writing to file!", Exclamation!) RETURN ; END IF ; // // Convert HTML file to Excel native format OLEObject Excel ; // Excel = CREATE OLEObject ; // IF Excel.ConnectToObject( docname ) = 0 THEN Excel.Application.DisplayAlerts = FALSE ; Excel.Application.Workbooks( 1 ).Parent.Windows( excel.Application.workbooks( 1 ).Name ).Visible = TRUE ; Excel.Application.Workbooks( 1 ).SaveAs(docname, 39 ) ; Excel.Application.Workbooks( 1 ).Close() ; END IF ; // DESTROY excel // // ...Done
Ce code est plus ou moins buggé : c'est un canevas que tu dois adapter
Hors ligne
Jette un coup d'oeil là dessus. Je me pencherai un peu plus sur ton cas pour faire les mises en forme demain mais déjà ça te permettra de te lancer. J'aurai mon bout de code que j'ai mis en place pour un cas un peu semblable, ce sera plus simple!
J'ai pas gagné mon titre de Power Excel pour rien!
A demain!
Hors ligne
2) 54€ c'est le prix d'une heure de prestation. Enorme en effet
Qu'est ce que tu as comme erreurs avec DW2xls ?
=> Carrement... Sinon le message d'erreur est le suivant : User fonction was not found (avec DataWindow en titre de boite de dialogue)
1) Tu l'enregistre au format html et tu force Excel à l'ouvrir (via OLE)
Depuis http://tech.groups.yahoo.com/group/Powe … werScript/ :
=> Je l'ai dejà testé hier ce code (j'ai cherché un peu sur le net comme toi lol) : le SAVEAS fonctionne mais pas la connexion à Excel via l'objet OLE renvoi toujours -7 soit File not found or file could not be opened. Le fichier étant pourtant bien présent (appel de la fonction testé avec docname = "c:\nomfichier.xls", "c:\nomfichier.txt" et "c:\nomfichier"). J'ai oublié un truc ?
Je vais testé ce matin le code proposé par Mr Pink Eyes.
Je tiens au jus pour l'avancement... dans la journée si ya du nouveau.
Merci.
Hors ligne
Pour donner suite à ma proposition, je te donne un nouveau lien qui regroupe pas mal de fonction de mise en forme des cellules Excel :
http://support.microsoft.com/kb/219151/fr
Je bidouille de mon coté pour tenter de te fournir une ébauche de script propre ;)
Hors ligne
Alors, je donne un début de code, qui contient notamment la création de l'objet, l'écriture d'un header et la sauvegarde du document :
long numcols , numrows , c, r OLEObject xlapp , xlsub, xlrng int ret // Set the # of columns and rows to process // Currently Set to copy the entire DW //numcols = long(dw_1.Object.DataWindow.Column.Count) numrows = dw_1.RowCount() // Create the oleobject variable xlapp xlApp = Create OLEObject // Connect to Excel and check the return code ret = xlApp.ConnectToNewObject( "Excel.Sheet" ) if ret < 0 then MessageBox("La connection à Excel a échoué !",string(ret)) return end if // Open a particular Excel file //xlApp.Application.Workbooks.Open("c:\test.xls") //,false,true // Make Excel visible xlApp.Application.Visible = true // Resolve the Excel reference once // This technique shortens the script and improves performance xlsub = xlapp.Application.ActiveWorkbook.Worksheets[1] //Write the headers xlsub.cells[1,1] = dw_1.Object.t_1.Text //t_1 étant le label qui contient le nom de la colonne xlsub.cells[1,1].font.bold=true //texte en gras xlsub.cells[1,1].Interior.ColorIndex = 36 //cellule avec un fond jaune clair // Save opened file xlApp.Application.Activeworkbook.Save() // SaveAs a different filename xlApp.Application.Activeworkbook.SaveAs("c:\file2.xls") // clean up xlApp.DisConnectObject() Destroy xlapp
Je continue pour voir si je trouve des trucs interressant. Je ne sais pas trop comment marche le système de COlorIndex (le 36 = jaune). Je continue de chercher mais ce ni plus ni moins que du VB.
Et pour l'autosize :
//Loop thru the Excel sheet columns to Autofit for c = 1 to 5 xlsub.cells[1,c].EntireColumn.AutoFit next
Après, si tu arrives à te servir du ->HTML->xls, je te le conseille car si ta mise en forme et très complexe, ça va te faire un beau paquet de lignes de code avec ma méthode.
Dernière modification par Mr Pink Eyes (28-08-2007 08:07:14)
Hors ligne
Ci joint une copie d'écran du resultat donné via la fonction de la librairie et du .pbd DW2XLS trouvé sur le net. En un appel de fonction j'ai le resultat suivant, c'est top mais bon faut passer 2 message d'erreurs avant quand même :
J'ai déjà un programme VB qui dessine un planning à l'écran et qui me mets en forme le tout zone d'impression y compris.
Dans l'absolu, je cherche un moyen générique (car on va me demander l'edition d'autre ecran avec DW dans peu temps, j'anticipe...) d'exporter une DW telle qu'affichée à l'écran dans une feuille excel... voilà tout lol. Une fois le programme écrit je serai peinard pour editer n'importe quel écran dans excel.
Apparement on a déjà écrit un objet PB qui utilise les objets OLE pour exporter des données de la base vers EXCEL, je vais donc mixer l'ensemble et voir ce que ca peut faire... c'est la mise en forme qui va etre chiante je le sens bien !
Hors ligne
il y a le programme de DW2XLS qui traine sur ce forum... il suffti apres de le cracker avec pbkiller... et tu recupereras la version originale... tu n'auras pas ces messages intempestifs...
Hors ligne
tu le trouveras dans "Cours, documentations...et divers"
Hors ligne
je voulais pas en parler mais bon j'ai bien téléchargé pbkiller hier pour decompiler le PBD de dw2xls. J'ai pas réussi alors si y avait moy de recup le code source ca le ferai bien ;-) ... carrément même !
Quel est la version qui fonctionne de ce programme PBKiller ? J'étais sur un site web chez des thai, chinois ou viet hier je sais pas trop mais c'était incompréhensible pour moi lol....
Dernière modification par fmxstyle (28-08-2007 09:19:46)
Hors ligne
pick ouic a écrit:
il y a le programme de DW2XLS qui traine sur ce forum... il suffti apres de le cracker avec pbkiller... et tu recupereras la version originale... tu n'auras pas ces messages intempestifs...
Pour économiser 55€ (ou 1h de travail) je ne crois pas que ça vaille le coup de cracker cette librairie.
Celà ruinera t'il votre employeur ?
Imaginez un écrivain qui vole des livres...
Dois je rappeler à quel point yBrowser était un bon produit ?
Que la boite a mis la clef sous la porte et que le produit a disparu ?
Les éditeurs d'add-ons PB sont fragiles
Hors ligne
Bonjour,
Sinon ce que tu peux faire et qui fonctionne bien, c'est faire le modèle sous excel et ensuite importer le modèle dans pb afin d'écrire les zones une à une.
si cette solution t'interesse, je peux te donner quelques exemples de codes.
Hors ligne
j'ai donné l'indice...
donc, en cherchant tu trouveras la version originale sur ce forum... et le pbkiller fonctionne bien.
Hors ligne
Les éditeurs d'add-ons PB sont fragiles
=> Je suis d'accord avec toi sur ce point, pas de soucis.
Sinon ce que tu peux faire et qui fonctionne bien, c'est faire le modèle sous excel et ensuite importer le modèle dans pb afin d'écrire les zones une à une.
=> Ok comment procéder ? Tu enregistre le traitement du modele que tu cree dans une macro ?
Hors ligne
long numcols , numrows , c, r
OLEObject xlapp , xlsub
int ret
// Set the # of columns and rows to process
// Currently Set to copy the entire DW
numcols = long(dw_1.Object.DataWindow.Column.Count)
numrows = dw_1.RowCount()
// Create the oleobject variable xlapp
xlApp = Create OLEObject
// Connect to Excel and check the return code
ret = xlApp.ConnectToNewObject( "Excel.Sheet" )
if ret < 0 then
MessageBox("La connection à Excel a échoué !",string(ret))
return
end if
// Open a particular Excel file
//xlApp.Application.Workbooks.Open("k:\test-bruno.xls") //,false,true
// Make Excel visible
xlApp.Application.Visible = true
// Resolve the Excel reference once
// This technique shortens the script and improves performance
xlsub = xlapp.Application.ActiveWorkbook.Worksheets[1]
// Loop thru the Datawindow and Excel sheet
// The for/next loop copies all rows for each column
For c = 1 to numcols
For r = 1 to numrows
xlsub.cells[r,c] = dw_1.object.data[r,c]
Next
Next
// Save opened file
//xlApp.Application.Activeworkbook.Save()
// SaveAs a different filename
//xlApp.Application.Activeworkbook.SaveAs("c:\file2.xls")
// clean up
messagebox("Fermeture du document","Avez-vous fini de vous servir du document ?")
xlApp.DisConnectObject()
Destroy xlapp
Le prob de la ligne en rouge est qu'elle me récupère le contenu de toutes les colonnes de la DW mais celles qui ne sont pas affichées, moi je n'en veux pas... Comment attaquer de manière générique les colonnes qui sont visible à l'écran ?
Dernière modification par fmxstyle (28-08-2007 09:59:15)
Hors ligne
Tu fais ton modèle dans Excel.
Ensuite dans PB, tu ouvre ce modèle et le sauvegarde sous un autre nom, puis tu va écrire l'ensemble de tes cellules une à une. Ainsi tous les formats faits dans Excel seront respectés ainsi que les éventuelles couleurs.
Pour ouvrir un fichier dans Excel et le sauvegarder.
String ls_message ,ls_directory , ls_fichier long result , ll_retour integer li_filenum , li_ret boolean lb_exist //Ouverture de l'application Excel Io_Excel = Create OLEObject result = Io_Excel.ConnectToNewObject("Excel.Application") IF result = 0 THEN //Mettre Excel visible pour controler ce qu'il fait.(pour les tests) Io_Excel.Application.Visible = false //Io_Excel.Application.Visible = True //ne pas voir les divers messages éventuels de Excel (sur les macro par exemple) Io_Excel.Application.DisplayAlerts = false // Io_Excel.Application.DisplayAlerts = True Io_Excel.Application.Workbooks.Open(as_fichier_modele) //controle si le fichier resultat existe lb_exist = FileExists(as_fichier_resultat) //Controle si le fichier est ouvert if lb_exist then li_filenum = FileOpen(as_fichier_resultat, LineMode!, Read!, LockReadWrite!) IF li_filenum = -1 THEN //gestion de l'erreur return -1 end if FileClose(li_FileNum) end if //Controle si le fichier existe afin de pouvoir le supprimer. IF lb_exist THEN FileDelete(as_fichier_resultat) END IF //sauvegarde de ce nouveau classeur sous un autre nom Io_Excel.Application.activeworkbook.SaveAs (as_fichier_resultat) //le workbook1 est le fichier de destination et le workbook2 est le fichier d'origine. END if return 0
Pour écrire les cellules tu peux utiliser ce code :
Io_Excel.Application.workbooks(ai_workbook).worksheets(as_worksheet).Cells(ai_ligne, ai_colonne).Value = as_value
Et n'oublie pas de sauvegarder le fichier quand tu as fini
Io_Excel.application.workbooks(1).Save Io_Excel.Application.DisplayAlerts = True //il y a toujours 2 classeurs ouverts le modele et le fichier résultat //le fichier résultat correspond au classeur1 //le modele correspond au classeur 2 mais lorsque le classeur 1 est fermé il devient à son tour classeur 1 Io_Excel.application.workbooks(1).close // Io_Excel.application.workbooks(1).close(false) fermer modele pas réouvert Io_Excel.quit() Io_Excel.disconnectobject() DESTROY Io_Excel
Hors ligne
fmxstyle a écrit:
Le prob de la ligne en rouge est qu'elle me récupère le contenu de toutes les colonnes de la DW mais celles qui ne sont pas affichées, moi je n'en veux pas... Comment attaquer de manière générique les colonnes qui sont visible à l'écran ?
Just a shoot in the dark :
For c = 1 to numcols IF dw_1.Describe("#c.Visible")=1 THEN For r = 1 to numrows xlsub.cells[r,c] = dw_1.object.data[r,c] Next End if Next
Wahouuuuu Wazou1812 !
Hors ligne
shahin a écrit:
Just a shoot in the dark :
Code: pb
For c = 1 to numcols IF dw_1.Describe("#c.Visible")=1 THEN For r = 1 to numrows xlsub.cells[r,c] = dw_1.object.data[r,c] Next End if Next
Je dirais plutot ...
For c = 1 to numcols IF dw_1.Describe("#"+string(c)+".Visible")='1' THEN For r = 1 to numrows xlsub.cells[r,c] = dw_1.object.data[r,c] Next End if Next
Hors ligne
Ouuups, oui bien sûr JCZ
ça m'apprendra à taper du code en aveugle
Hors ligne
JCZ a écrit:
shahin a écrit:
Just a shoot in the dark :
Code: pb
For c = 1 to numcols IF dw_1.Describe("#c.Visible")=1 THEN For r = 1 to numrows xlsub.cells[r,c] = dw_1.object.data[r,c] Next End if NextJe dirais plutot ...
Code: pb
For c = 1 to numcols IF dw_1.Describe("#"+string(c)+".Visible")='1' THEN For r = 1 to numrows xlsub.cells[r,c] = dw_1.object.data[r,c] Next End if Next
J'irai plus loin en faisant un evaluate du .visible, car en cas de formule cela ne marche plus
For c = 1 to numcols For r = 1 to numrows IF dw_1.Describe("Evaluate('#"+string(c)+".Visible', "+ string(r) + ")"='1' THEN xlsub.cells[r,c] = dw_1.object.data[r,c] End if Next Next
Hors ligne
J'vois qu'on s'inspire de "mon" code finalement
Hors ligne
Mr Pink Eyes a écrit:
J'vois qu'on s'inspire de "mon" code finalement
C'est marrant l'objet Excel de ma bibliothèque perso ressemble aussi à ça.
Comme quoi les mêmes problèmes génèrent souvent les mêmes solutions
Hors ligne
Chrnico a écrit:
Mr Pink Eyes a écrit:
J'vois qu'on s'inspire de "mon" code finalement
C'est marrant l'objet Excel de ma bibliothèque perso ressemble aussi à ça.
Comme quoi les mêmes problèmes génèrent souvent les mêmes solutions
ouais, mais dans ton code t'as pas
// Open a particular Excel file //xlApp.Application.Workbooks.Open("k:\test-bruno.xls") //,false,true
Dernière modification par Mr Pink Eyes (28-08-2007 11:33:28)
Hors ligne
Mr Pink Eyes a écrit:
ouais, mais dans ton code t'as pas ...
tu t'appelle Bruno ?
J'adore ta signature Bruno !
Hors ligne
Mr Pink Eyes a écrit:
Chrnico a écrit:
Mr Pink Eyes a écrit:
J'vois qu'on s'inspire de "mon" code finalement
C'est marrant l'objet Excel de ma bibliothèque perso ressemble aussi à ça.
Comme quoi les mêmes problèmes génèrent souvent les mêmes solutionsouais, mais dans ton code t'as pas
Code: pb
// Open a particular Excel file //xlApp.Application.Workbooks.Open("k:\test-bruno.xls") //,false,true
Non, mais mon code traite aussi les computes, il limite à 255 colonnes l'export (hé oui faut y penser), il ne prend pas les colonnes dont toutes les lignes sont vides, il récupère les libellés de DDDW ou DDLB et non leur valeur, il permet de changer l'ordre des colonnes à l'export grace à un code dans le tag de la colonne, etc...
Hors ligne