1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| void __fastcall MyTools::XLSExport(TDataSet* source,AnsiString dest)
{
bool QuitExcelToEnd;
Variant vFilename, vSaveChanges;
Variant vMSExcel, vXLWorkbook, vXLWorkbooks, vWorksheet, vRange, vCell, vValue, vColl;
int NumLine = 1; // contient le numéro de la ligne où l'on commence à écrire les données sous Excel
int NumCol = 65; // "A" code ASCII 65 (réf. à la 1ère colonne sous Excel)
try
{
vMSExcel = Variant::GetActiveObject("Excel.Application"); // Capture d'une instance existante d'Excel
}
// Si Excel n'est pas déjà ouvert, une exception est levée ...
catch(EOleSysError& )
{
vMSExcel = Variant::CreateObject("Excel.Application"); // Si Excel n'est pas lancé, on l'exécute
}
vMSExcel.OlePropertySet("Visible", true);
QuitExcelToEnd = false; // On ne fermera pas Excel après le traitement.
vMSExcel.OlePropertySet("WindowState", -4140 );
vXLWorkbooks = vMSExcel.OlePropertyGet("Workbooks"); // Récupération du pointeur vers la collection des Workbooks
vXLWorkbook = vXLWorkbooks.OleFunction("Add"); // Ajout d'un nouveau Workbook à la collection
vWorksheet = vXLWorkbook.OlePropertyGet("Worksheets","Feuil1"); // On active le sheet par défaut "Feuil1"
source->First(); // On se place sur le 1er enregistrement de la requête
for (int j = 0; j < source->FieldCount; j++) // ... et son nb de champs pr libellés colonnes
{
AnsiString Ref = ""; // contiendra la référence à la cellule Excel, i.e. "A1"
Ref.cat_sprintf("%c%d", NumCol+j, NumLine); // donne "A1" pour 65 et 1
vRange = StringToOleStr(Ref); // Ref est converti en Range (bien qu'il s'agisse toujours d'un Variant)
vCell = vWorksheet.OlePropertyGet("Range", vRange);// récupération du pointeur vers la cellule sélectionnée ("A1")
vValue = StringToOleStr(source->Fields->Fields[j]->DisplayName);
vCell.OlePropertySet("Value", vValue); // affectation de la valeur de la requête à la cellule référencée ("A1")
}
NumLine = 2; //on se place sur la ligne suivant les libellés...
for (int t = 0; t < source->RecordCount; t++) // nb d'enregistrements de la requête
{
for (int i = 0; i < source->FieldCount; i++) // ... et son nb de champs
{
AnsiString Ref = ""; // contiendra la référence à la cellule Excel, i.e. "A1"
Ref.cat_sprintf("%c%d", NumCol+i, NumLine+t); // donne "A1" pour 65 et 1
vRange = StringToOleStr(Ref); // Ref est converti en Range (bien qu'il s'agisse toujours d'un Variant)
vCell = vWorksheet.OlePropertyGet("Range", vRange);// récupération du pointeur vers la cellule sélectionnée ("A1")
vValue = StringToOleStr(source->Fields->Fields[i]->AsString);
vCell.OlePropertySet("Value", vValue); // affectation de la valeur de la requête à la cellule référencée ("A1")
}
source->Next(); // on passe à l'enregistrement suivant
}
vFilename = StringToOleStr(dest); // le nom de fichier de la SaveDialog est converti au format OLE
vMSExcel.OlePropertySet("DisplayAlerts", true); // on désactive les DisplayAlerts d'Excel (pour éviter les messages d'overwriting d'Excel)
vXLWorkbook.OleProcedure("Saveas", vFilename); // sauvegarde du fichier sous le nom préalablement sélectionné
vSaveChanges = true; // true : modif save, false : not save, Unassigned : demande à l'utilisateur
//vXLWorkbook.OleFunction("Close", vSaveChanges, vFilename); // fermeture du classeur qui a recueilli les données
vMSExcel.OlePropertySet("DisplayAlerts", true); // réactivation des DisplayAlerts
if (QuitExcelToEnd) // Excel doit-il être fermé ?
{ // Si oui ...
vMSExcel.OleFunction("Quit"); // on le ferme
vMSExcel = Unassigned; // ... et le pointeur de son instance est réinitialisé
}
} |
Partager