Bonjour,
j'ai résolu mes problèmes (format DATE et lenteur du transfert de données), et je souhaitais en faire profiter les autres qui se prennent la tête avec Excel via c#.
Pour chercher directement ce qui vous interesse, j'ai essayé de mettre des couleurs... donc, pour les dates et la lenteurs, cherchez le rouge!!
++
//script C# qui génère un doc Excel à partir d'une DataTable (en fait, d'un datagrid chez moi) de .NET d'un formulaire windows (une appli windows, pas web, j'ai pas testé)
// spécificité que j'ai eu du mal à trouver sur le net : formattage d'une colonne Excel en date + vitesse de copie (la plupart des scripts sur le net vous montrent comment copier cellule par cellule... moi, j'avais 35 colonnes et 200 lignes, ça prenait 40 secondes... nul!!!)
public static void OuvreExcel(DataTable requete)
{
DialogResult resu;
resu = MessageBox.Show("Cette fonctionnalité permet de générer un tableau Excel de votre grille de résultat. Confirmez-vous la création?", "POUET-POUET", MessageBoxButtons.YesNo);
if (resu == DialogResult.No)
return;
try
{
/*******************
//Pour chercher un fichier déjà existant on peut faire ça :
//Attention : il faut que dans votre fichier il y ait : une feuille appelée Feuil1 ET que le select se pose sur cette Feuil1 (n'importe où, mais pas sur une autre feuille avec d'autres données!
// il n'y ait pas : de feuille qui s'appelle déjà comme ça : "Données du " + todaySheet... donc, renommer vos feuilles si vous le faites 2 fois de suite
FileDialog fenetre = new OpenFileDialog();
fenetre.DefaultExt = ".xls";
fenetre.InitialDirectory = @"P:\APP\SATURNE.DEM\docs\";
fenetre.Title = "Spécifier l'emplacement ainsi que le nom du fichier que vous désirez créé : exemple SATURNE_donnees_tableauMedicaments_date.xls";
fenetre.ShowDialog();
string fileName = fenetre.FileName;
//Pour pouvoir ensuite utiliser xlClasseur = xlApp.Workbooks.Open(fileName, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing);
//à laplace de xlClasseur = xlApp.Workbooks.Add(Missing) 7 lignes plus bas
********************/
//Déclaration d'un objet à tout faire : le Missing (simple, office permet de tenter un tas de renseignement à l'exécution d'une appli... mais ici, on n'en a pas besoin, alors on remplace ça par un Missing... pratique nan?)
object Missing = System.Reflection.Missing.Value;
//Instanciation de l'appli
Excel._Application xlApp;
Excel._Workbook xlClasseur;
Excel._Worksheet xlFeuill1;
xlApp = new Excel.Application();
xlApp.Visible = true;
xlClasseur = xlApp.Workbooks.Add(Missing);
//la feuille de travail
Excel.Sheets xlFeuilles = xlClasseur.Sheets;
xlFeuill1 = (Excel._Worksheet)xlFeuilles["Feuil1"];
//Renommage de la feuille Excel : "Données du jour"
string todaySheet = DateTime.Now.ToShortDateString().Replace('/', ' '); on remplace les / par des espaces pour faire + aéré... y a peut être aussi une autre raison, je me rappelle plus
xlFeuill1.Name = "Données du " + todaySheet;
//nombre de lignes et de colonnes de la table (oui, ma table s'appelle requete, et vous?)
int nbRow = requete.Rows.Count;
int nbCol = requete.Columns.Count;
//Formattage des entêtes de colonne
//je ne sais pas comment faire autrement qu'en passant toujours par des get_Range( , ) à 2 arguments qui prend des cellules, et comme j'avais suffisamment cherché à mon goût...!
string plage = "AI";
switch (nbCol)
{
case 34 : plage = "AH"; //remplacez ici par le nombre de colonne de votre table en translatant avec l'alphabet (A=1, B=2)
break;
case 35 : plage = "AI";
break;
case 36 : plage = "AJ";
break;
}
//Début du VRAI formattage
xlFeuill1.Cells.Font.Size = 11; //on écrit en police 11, le 10 est trop petit pour mes utilisateurs
string plageSelected = plage + "1"; //en fonction de votre nombre de colonne, prendre toutes les cellules de l'entête
Excel.Range rg = xlFeuill1.get_Range("A1",plageSelected); //sélection des celulles de A1 à AI1
rg.Select(); //en fait, c'est ça une sélection
rg.Font.Bold = true; //en gras
rg.WrapText = true; //renvoyer à la ligne automatiquement
rg.HorizontalAlignment = Excel.Constants.xlCenter; //centrer
rg.Interior.ColorIndex = 40; //colorier en orange (je suis née en 77, c'est donc la couleur de mon transat, de mon berceau et de la moitié de mes fringues sur les photos de bébés...
rg.Borders.Weight = 3; //cadre épais
rg.Borders.LineStyle = Excel.Constants.xlSolid; //??
rg.Cells.RowHeight = 68; //ma hauteur de ligne pour l'entête (vu que c'est renvoyé à la ligne automatiquement)
rg.Cells.ColumnWidth = 12; //largeur de colonne par défaut
//sinon y a ça : l'autofit, il va chercher à calibrer la largeur de colonne en fonction de ce que vous avez dedans!
//xlFeuill1.Columns.EntireColumn.AutoFit();
//colonnes spéciales
xlFeuill1.get_Range("B1", "B1" ).ColumnWidth = 50; //ma 2ième devait être large (plus large que 12, la valeur par défaut)
xlFeuill1.get_Range("C1", "C1" ).ColumnWidth = 25;
xlFeuill1.get_Range("L1", "L1" ).ColumnWidth = 25;
xlFeuill1.get_Range("AE1", "AG1" ).ColumnWidth = 0; //permet d'avoir la colonne en masquée (mes utilisateurs ne veulent pas cette colonne... jusqu'à ce qu'ils décident un jour que ce sserait bien de l'avoir...)
//j'ai cherché partout cette commande magique : vous avez des dates qui s'affichent en 38540? moi aussi, c'est pas drôle, hein?
// en fait, en sélectionnant la colonne, on peut lui dire que c'est en format date
//si vous avec une version française d'excel, la date c'est jj/mm/aaaa, en version anglaise ce serait donc mm/dd/yyyy ou pour les faux anglais dd/mm/yyyy!!
xlFeuill1.get_Range("I2", "I"+Convert.ToString(nbRow+1)).NumberFormat = "jj/mm/aaaa"; //LES DATES!! on dit "@" pour spécifier que c'est du texte, "0.00" pour dire que ce sont des chiffres à 2 virgules, et rien pour dire que c'est "standard"
//remplissage des entêtes
int iCol = 1;
foreach (DataColumn column in requete.Columns)
{
xlFeuill1.Cells[1, iCol] = column.ColumnName.ToString(); //on remplit colonne par colonne
iCol = iCol + 1;
}
//copie du dataGrid
int i,j;
//création d'un tableau temporaire (accélération du remplissage : cellule par cellule c'est bien mais long : 40 secondes pour 7000 cellules... et ça m'arrivait d'en avoir plus!!)
object[,] tableauDeDonnees = new object[nbRow,nbCol]; //tableau 2 dimensions
for (i = 0 ; i < nbRow ; i++)
{
for (j = 0; j < nbCol ; j++)
{
tableauDeDonnees[i,j] = requete.Rows[i].ItemArray.GetValue(j);
}
}
plageSelected = plage + Convert.ToString(nbRow+1); //chez moi, il fallait sélectionner A2 à AI201
xlFeuill1.get_Range("A2", plageSelected).Value2 = tableauDeDonnees; //la copie se fait là ! et c'est instantané...
}
catch(Exception ex)
{
MessageBox.Show("Il y a eu une erreur :il se peut que le tableau à copier soit trop important ou comporte une colonne qui provoque une erreur. Peut être n'avez-vous pas excel ou XP. Le message d'erreur du logiciel est : " + ex.Message);
}
}
//Appel de la fonction sur un datagrid
private void btnExcel_Click(object sender, System.EventArgs e)
{
OuvreExcel(((DataTable)(dataGridRechercheSpePharma.DataSource)));
}
N'hésitez pas à faire vos commentaires