Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

IMPORTER/EXPORTER FACILEMENT VOS DONNÉES SOUS DIFFÉRENTS FORMATS


Information sur la source

Catégorie :Base de Donnees Source .NET ( DotNet ) Classé sous : importer, exporter, données, migration, echange Niveau : Initié Date de création : 03/11/2006 Date de mise à jour : 07/04/2008 20:27:42 Vu / téléchargé: 12 191 / 2 546

Note :
7 / 10 - par 1 personne
7,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (4)
Ajouter un commentaire et/ou une note


Description

Dans mes développements quotidiens, j'avais besoin d'une API qui facilite l'importation et l'exportation de données sous différents formats. Malheureusement, la plupart des APIs disponibles sur la toile ne se préoccupent que de l'exportation. Qui plus est, elles ont la fâcheuse habitude d'ajouter des éléments de mise en forme aux documents générés qui les rendent difficilement modifiables (cf. Crystal Reports). Le seul outil véritablement fiable que j'ai trouvé c'est le service DTS de SQL server. Cependant, son utilisation dans une application .NET complique un peu le déploiement. Tout ceci m'a donc amené à chercher une solution personnelle. Dans cette source, je vous propose une classe utilitaire qui gère l'importation et l'exportation des données sous quatre formats: XML, CSV, Document Word et Classeur Excel. La démo n'est pas très exsaustive mais bon...A vous de définir la façon dont vous l'utiliserez. Les difficultés de déploiement sont moindre car il suffit que l'utilisateur final dispose de MS Office (Il est rare que ce ne soit pas le cas).
 

Source

  • Imports System.IO
  • Imports Addy.Utilities
  • '==================================================================================
  • ' Englobe les fonctionnalités d'échange de données avec les applications les plus
  • ' courantes. Gère l'importation et l'exportation du contenu d'un DataSet ADO.NET
  • ' sous l'un des formats suivants: XML, CSV, Document Word et Classeur Excel.
  • '==================================================================================
  • Public Class DataExchange
  • #Region " Constantes "
  • Const WORD_MAX_ROWS As Integer = 32767
  • Const EXCEL_MAX_ROWS As Integer = 65535
  • Const DEFAULT_FIELD_SEPARATOR As Char = ";"c
  • #End Region
  • #Region " Export "
  • #Region " Generique "
  • ' Permet d'exporter les données d'un DataSet vers un fichier.
  • ' L'extension du nom de fichier permet de déviner le format.
  • Public Shared Sub Export(ByVal dataSet As DataSet, ByVal fileName As String)
  • Dim ext As String = Path.GetExtension(fileName)
  • Select Case ext.ToLower()
  • Case ".xml"
  • ExportXml(dataSet, fileName)
  • Case ".csv"
  • ExportCSV(dataSet.Tables(0), fileName)
  • Case ".doc"
  • ExportWord(dataSet, fileName)
  • Case ".xls"
  • ExportExcel(dataSet, fileName)
  • Case Else
  • Throw New InvalidOperationException("Ce format de fichier n'est pas pris en charge")
  • End Select
  • End Sub
  • #End Region
  • #Region " XML "
  • ' Exporte les données d'un DataSet vers un document XML
  • Public Shared Sub ExportXml(ByVal dataSet As DataSet, ByVal fileName As String)
  • dataSet.WriteXml(fileName)
  • End Sub
  • ' Exporte une plage de données d'un DataTable vers un document XML
  • Public Shared Sub ExportXml(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
  • ' On crée un DataSet et on y met une copie du DataTable
  • Dim dataSet As New dataSet(dataTable.TableName)
  • Dim dtClone As dataTable = dataTable.Clone()
  • dataSet.Tables.Add(dtClone)
  • ' Par la suite, on transfarère une copie des lignes à exporter dans la copie du DataTable
  • Dim i As Integer = startIndex
  • Dim n As Integer = Math.Min(startIndex + rowCount, dataTable.Rows.Count)
  • While i < n
  • dtClone.ImportRow(dataTable.Rows(i))
  • i += 1
  • End While
  • ' On termine en enregistrant le tout au format XML
  • dataSet.WriteXml(fileName)
  • End Sub
  • ' Exporte toutes les données d'un DataTable vers un document XML
  • Public Shared Sub ExportXml(ByVal dataTable As DataTable, ByVal fileName As String)
  • ExportXml(dataTable, fileName, 0, Integer.MaxValue)
  • End Sub
  • #End Region
  • #Region " CSV "
  • ' Exporte une plage de données d'un DataTable vers un fichier texte
  • ' Chaque enregistrement sera écrit sur une seule ligne. Un caractère spécial sera
  • ' utilisé comme séparatier de champs. Un autre sera utilisé pour entourer les champs.
  • Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String, _
  • ByVal startIndex As Integer, ByVal rowCount As Integer, ByVal fieldSeparator As Char, _
  • ByVal fieldContainer As Char)
  • ' Ouvrir un fichier texte en écriture
  • Dim csvFile As New StreamWriter(fileName)
  • Dim n As Integer = dataTable.Columns.Count
  • ' Ecrire les noms de colonnes sur la première ligne en les séparant par des points-virgules
  • For j As Integer = 0 To n - 2
  • csvFile.Write(DataFormat.QuotedString(dataTable.Columns(j).ColumnName, fieldContainer))
  • csvFile.Write(fieldSeparator)
  • Next j
  • csvFile.WriteLine(DataFormat.QuotedString(dataTable.Columns(n - 1).ColumnName, fieldContainer))
  • ' Ecrire chaque enregistrement par la suite en respectant la même logique
  • Dim i As Integer = startIndex
  • Dim m As Integer = Math.Min(startIndex + rowCount, dataTable.Rows.Count)
  • While i < m
  • For j As Integer = 0 To n - 2
  • csvFile.Write(DataFormat.QuotedString(Convert.ToString(dataTable.Rows(i)(j)), fieldContainer))
  • csvFile.Write(fieldSeparator)
  • Next j
  • csvFile.WriteLine(DataFormat.QuotedString(Convert.ToString(dataTable.Rows(i)(n - 1)), fieldContainer))
  • i += 1
  • End While
  • ' Fermer le fichier
  • csvFile.Close()
  • End Sub
  • ' Une surchage pour laquelle fieldSeparator vaut le poit-virgule tandis que fieldContainer est le caractère nul (donc pas de conteneur de champs)
  • Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
  • ExportCSV(dataTable, fileName, startIndex, rowCount, DEFAULT_FIELD_SEPARATOR, Char.MinValue)
  • End Sub
  • ' Une surchage sans borne (on exporte toute la table)
  • Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String, ByVal fieldSeparator As Char, ByVal fieldContainer As Char)
  • ExportCSV(dataTable, fileName, 0, Integer.MaxValue, fieldSeparator, fieldContainer)
  • End Sub
  • ' Une surchage sans borne et pour laquelle fieldSeparator vaut le poit-virgule tandis que fieldContainer est le caractère nul
  • Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String)
  • ExportCSV(dataTable, fileName, 0, Integer.MaxValue, DEFAULT_FIELD_SEPARATOR, Char.MinValue)
  • End Sub
  • ' Exporte les données d'un DataSet vers un ensemble de fichiers texte à valeurs separées par des caractères spéciaux.
  • ' Chaque table est exportée vers un fichier distinct. Tous ces fichiers sont regroupés dans le même dossier
  • Public Shared Sub ExportCSV(ByVal dataSet As DataSet, ByVal dirName As String, ByVal fieldSeparator As Char, ByVal fieldContainer As Char)
  • ' On crée le répertoire du groupe...
  • If Not Directory.Exists(dirName) Then
  • Directory.CreateDirectory(dirName)
  • End If
  • ' ...et on exporte chaque jeu d'enregistrements du groupe de données vers un fichier qui porte son nom
  • For Each table As DataTable In dataSet.Tables
  • ExportCSV(table, Path.Combine(dirName, table.TableName & ".csv"), fieldSeparator, fieldContainer)
  • Next
  • End Sub
  • ' Exporte les données d'un DataSet vers un ensemble de fichiers texte à valeurs separées par des point-virgules.
  • Public Shared Sub ExportCSV(ByVal dataSet As DataSet, ByVal dirName As String)
  • ExportCSV(dataSet, dirName, DEFAULT_FIELD_SEPARATOR, Char.MinValue)
  • End Sub
  • #End Region
  • #Region " Word "
  • ' Exporte les données d'un DataSet vers un document Word
  • Public Shared Sub ExportWord(ByVal dataSet As DataSet, ByVal fileName As String)
  • ' Lancer Word en arrière-plan
  • Dim wordApp As New Word.ApplicationClass
  • Try
  • ' Créer un nouveau document
  • Dim document As Word.Document = wordApp.Documents.Add()
  • ' Définir Arial (taille 10) comme police par défaut du document
  • Dim range As Word.Range = document.Content
  • range.Font.Name = "Arial"
  • range.Font.Size = 10
  • ' Exporter chaque DataTable dans un tableau spécifique
  • For Each dataTable As dataTable In dataSet.Tables
  • ExportWord(dataTable, document, range, 0, WORD_MAX_ROWS)
  • SkipToNextParagraph(range)
  • Next
  • ' Enregistrer le document sous le chemin spécifié
  • document.SaveAs(CObj(fileName))
  • Catch ex As System.Runtime.InteropServices.COMException
  • Throw New ApplicationException(ex.Message, ex)
  • Finally
  • ' Quitter Word
  • wordApp.Quit()
  • End Try
  • End Sub
  • ' Exporte une plage de données d'un DataTable vers un document Word
  • Public Shared Sub ExportWord(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
  • ' Lancer Word en arrière-plan
  • Dim wordApp As New Word.ApplicationClass
  • Try
  • ' Créer un nouveau document
  • Dim document As Word.Document = wordApp.Documents.Add()
  • ' Définir Arial (taille 10) comme police par défaut du document
  • Dim range As Word.Range = document.Content
  • range.Font.Name = "Arial"
  • range.Font.Size = 10
  • ' Exporter la plage de DataRows dans un tableau spécifique
  • ExportWord(dataTable, document, range, startIndex, rowCount)
  • ' Enregistrer le document sous le chemin spécifié
  • document.SaveAs(CObj(fileName))
  • Catch ex As System.Runtime.InteropServices.COMException
  • Throw New ApplicationException(ex.Message, ex)
  • Finally
  • ' Quitter Word
  • wordApp.Quit()
  • End Try
  • End Sub
  • ' Exporte toutes les données d'un DataTable vers un document Word
  • Public Shared Sub ExportWord(ByVal dataTable As DataTable, ByVal fileName As String)
  • ExportWord(dataTable, fileName, 0, WORD_MAX_ROWS)
  • End Sub
  • ' Définit la logique d'exportation vers Word à proprement parler
  • Private Shared Sub ExportWord(ByVal dataTable As DataTable, ByVal document As Word.Document, ByVal range As Word.Range, ByVal startIndex As Integer, ByVal rowCount As Integer)
  • Dim m As Integer = Math.Min(rowCount, WORD_MAX_ROWS - 2)
  • Dim n As Integer = dataTable.Columns.Count
  • With document.Tables.Add(range, m + 2, n) ' Créer un tableau dans la plage "range"
  • .Cell(1, 1).Merge(.Cell(1, n)) ' Fusionner toutes les cellules de la première ligne du tableau
  • With .Cell(1, 1).Range ' Mettre l'unique cellule de cette ligne en forme et lui affecter le nom du DataTable
  • .Shading.BackgroundPatternColor = Word.WdColor.wdColorGray15
  • .ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter
  • .Font.Size = 16
  • .Bold = True
  • .Text = dataTable.TableName
  • End With ' Cell(1, 1).Range
  • ' Les cellules de la deuxième ligne contiendront les noms de colonnes
  • For i As Integer = 0 To n - 1
  • With .Cell(2, i + 1).Range
  • .ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter
  • .Bold = True
  • .Text = dataTable.Columns(i).ColumnName
  • End With ' Cell(2, i + 1).Range
  • Next i
  • ' Les autres cellules du tableau contiendront les valeurs du DataTable
  • Dim k As Integer = startIndex, l As Integer = 3
  • Dim m2 As Integer = Math.Min(startIndex + m, dataTable.Rows.Count)
  • While k < m2
  • For j As Integer = 0 To n - 1
  • .Cell(l, j + 1).Range.Text = Convert.ToString(dataTable.Rows(k)(j))
  • Next j
  • l += 1
  • k += 1
  • End While
  • .AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitContent) ' Ajuster la taille du tableau à son contenu
  • .Borders.OutsideLineStyle = Word.WdLineStyle.wdLineStyleSingle ' Encadrer le tableau à l'exterieur...
  • .Borders.InsideLineStyle = Word.WdLineStyle.wdLineStyleSingle ' ...et à l'intérieur (afficher le quadrillage)
  • End With ' Word.Tables.Add
  • End Sub
  • #End Region
  • #Region " Excel "
  • ' Exporte les données d'un DataSet vers un classeur Excel
  • Public Shared Sub ExportExcel(ByVal dataSet As DataSet, ByVal fileName As String)
  • ' Lancer Excel en arrière-plan
  • Dim excelApp As New Excel.ApplicationClass
  • Try
  • Dim workBook As Excel.Workbook = excelApp.Workbooks.Add()
  • ' Avant de continuer, on enregistre les feuilles par défaut créées
  • ' dans le classeur afin de pouvoir les supprimer plus tard
  • Dim defaultSheets As New ArrayList
  • For i As Integer = 1 To workBook.Sheets.Count
  • defaultSheets.Add(workBook.Sheets(i))
  • Next
  • ' On parcourre la collection de DataTables du DataSet et
  • ' on crée une feuille de calcul pour chacun
  • For Each table As DataTable In dataSet.Tables
  • ExportExcel(table, workBook, 0, Integer.MaxValue)
  • Next
  • ' Supprimer les feuilles par défaut (Feuil1...Feuil3 ou Sheet1...Sheet3 ou...)
  • ' Il est impossible de les supprimer toutes au départ car un classeur Excel
  • ' doit toujours conténir une feuille au moins
  • For Each worksheet As Excel.Worksheet In defaultSheets
  • worksheet.Delete()
  • Next
  • ' Sauvegarder le classeur
  • workBook.SaveAs(fileName)
  • Catch ex As System.Runtime.InteropServices.COMException
  • Throw New ApplicationException(ex.Message, ex)
  • Finally
  • ' Quitter Excel
  • excelApp.Quit()
  • End Try
  • End Sub
  • ' Exporte une plage de données de DataTable vers un classeur Excel
  • Public Shared Sub ExportExcel(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
  • ' Lancer Excel en arrière-plan
  • Dim excelApp As New Excel.ApplicationClass
  • Try
  • Dim workBook As Excel.Workbook = excelApp.Workbooks.Add()
  • ' Avant de continuer, on enregistre les feuilles par défaut créées
  • ' dans le classeur afin de pouvoir les supprimer plus tard
  • Dim defaultSheets As New ArrayList
  • For i As Integer = 1 To workBook.Sheets.Count
  • defaultSheets.Add(workBook.Sheets(i))
  • Next
  • ' On crée une feuille de calcul pour le DataTable
  • ExportExcel(dataTable, workBook, startIndex, rowCount)
  • ' Supprimer les feuilles par défaut (Feuil1...Feuil3 ou Sheet1...Sheet3 ou...)
  • ' Il est impossible de les supprimer toutes au départ car un classeur Excel
  • ' doit toujours conténir une feuille au moins
  • For Each worksheet As Excel.Worksheet In defaultSheets
  • worksheet.Delete()
  • Next
  • ' Sauvegarder le classeur
  • workBook.SaveAs(fileName)
  • Catch ex As System.Runtime.InteropServices.COMException
  • Throw New ApplicationException(ex.Message, ex)
  • Finally
  • ' Quitter Excel
  • excelApp.Quit()
  • End Try
  • End Sub
  • ' Exporte toutes les données de DataTable vers un classeur Excel
  • Public Shared Sub ExportExcel(ByVal dataTable As DataTable, ByVal fileName As String)
  • ExportExcel(dataTable, fileName, 0, Integer.MaxValue)
  • End Sub
  • Private Shared Sub ExportExcel(ByVal dataTable As DataTable, ByVal workBook As Excel.Workbook, ByVal startIndex As Integer, ByVal rowCount As Integer)
  • Dim m As Integer = Math.Min(Math.Min(rowCount, dataTable.Rows.Count), EXCEL_MAX_ROWS)
  • Dim n As Integer = dataTable.Columns.Count
  • With CType(workBook.Worksheets.Add(), Excel.Worksheet)
  • .Name = dataTable.TableName ' Le nom de la feulle est celui du DataTable
  • ' La première ligne de la feuille contient les noms de colonnes
  • Dim headers(n - 1) As String
  • For i As Integer = 0 To n - 1
  • headers(i) = dataTable.Columns(i).ColumnName
  • Next
  • ' Définir la ligne d'en-tête
  • With .Range(GetExcelRange(0, 0, 0, n - 1))
  • .Font.Bold = True
  • .HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter
  • .Value2 = headers
  • End With
  • ' Les autres lignes contiennent les données du jeu d'enregistrements
  • Dim k As Integer = startIndex, l As Integer = 0
  • Dim m2 As Integer = Math.Min(startIndex + rowCount, m)
  • Dim values(m - 1, n - 1) As String ' toutes les valeurs seront exportés sous-forme de texte
  • While k < m2
  • For j As Integer = 0 To n - 1
  • values(l, j) = Convert.ToString(dataTable.Rows(k)(j))
  • Next
  • l += 1
  • k += 1
  • End While
  • ' Définir les valeurs de cellule
  • .Range(GetExcelRange(1, 0, m, n - 1)).Value2 = values
  • ' Définir la zone d'impression à la plage nouvellement créée
  • Dim printArea As String = GetExcelRange(0, 0, m, n - 1)
  • .PageSetup.PrintArea = printArea
  • .Range(printArea).Columns.AutoFit()
  • End With
  • End Sub
  • #End Region
  • #End Region
  • #Region " Import "
  • #Region " Générique "
  • ' Permet d'importer les données d'un DataSet depuis un fichier.
  • ' L'extension du nom de fichier permet de déviner le format.
  • ' DataExchange n'a aucune idée du SGBD à partir duquel les données seront importées.
  • ' Pour cette raison, le schema du groupe de données doit avoir été créé avant l'appel de cette méthode.
  • ' La méthode FillSchema des DataAdapters peut être utilisée à cet effet.
  • ' Si des colonnes ont été renommées dans la table de destination, ouvrir
  • ' le document source et y renommer les colonnes avant l'importation.
  • ' Les colonnes qui ne sont pas mappées dans le schema du DataSet seront ignorées.
  • ' La même politique s'applique aux tables.
  • ' La mise à jour effective peut se faire soit en invoquant la méthode Update d'un DataAdapter,
  • ' Soit en parcourrant chaque jeu d'enregistrements et en exécutant un ordre SQL INSERT
  • Public Shared Sub Import(ByVal dataSet As DataSet, ByVal fileName As String)
  • Dim ext As String = Path.GetExtension(fileName)
  • Select Case ext.ToLower()
  • Case ".xml"
  • ImportXml(dataSet, fileName)
  • Case ".csv"
  • ImportCSV(dataSet.Tables(0), fileName)
  • Case ".doc"
  • ImportWord(dataSet, fileName)
  • Case ".xls"
  • ImportExcel(dataSet, fileName)
  • Case Else
  • Throw New InvalidOperationException("Ce format de fichier n'est pas pris en charge")
  • End Select
  • End Sub
  • #End Region
  • #Region " XML "
  • ' Importe les données d'un DataSet depuis un document XML
  • Public Shared Sub ImportXml(ByVal dataSet As DataSet, ByVal fileName As String)
  • dataSet.ReadXml(fileName)
  • End Sub
  • ' Importe une plage de données d'un DataTable vers un document XML
  • Public Shared Sub ImportXml(ByVal dataTable As DataTable, ByVal fileName As String)
  • ' On lit le document XML à partir d'un DataSet ...
  • Dim dataSet As New dataSet
  • dataSet.ReadXml(fileName)
  • ' ...et on importe le contenu du DataSet dans dataTable
  • For Each row As DataRow In dataSet.Tables(dataTable.TableName).Rows
  • dataTable.ImportRow(row)
  • Next
  • End Sub
  • #End Region
  • #Region " CSV "
  • ' Importe les données d'un DataSet depuis un fichier texte à valeurs separées par des points-virgules.
  • ' Dans ce cas, fileName est sensé désigner un répertoire plutôt qu'un fichier
  • Public Shared Sub ImportCSV(ByVal dataSet As DataSet, ByVal dirName As String)
  • For Each table As DataTable In dataSet.Tables
  • Dim fileName As String = Path.Combine(dirName, table.TableName & ".csv")
  • If File.Exists(fileName) Then ImportCSV(table, fileName)
  • Next
  • End Sub
  • ' Importe les données d'un DataTable depuis un fichier texte à valeurs separées par des points-virgules
  • Public Shared Sub ImportCSV(ByVal dataSet As DataSet, ByVal tableName As String, ByVal fileName As String)
  • ImportCSV(dataSet.Tables(tableName), fileName)
  • End Sub
  • ' Importe les données d'un DataTable depuis un fichier texte à valeurs separées par des points-virgules
  • Public Shared Sub ImportCSV(ByVal dataTable As DataTable, ByVal fileName As String)
  • ' Ouvrir le fichier et lire son contenu d'une seule traite
  • Dim csvFile As New StreamReader(fileName)
  • Dim csvContent As String = csvFile.ReadToEnd()
  • csvFile.Close()
  • ' Décomposer le contenu du fichier en lignes
  • Dim csvLines() As String = csvContent.Split(vbCrLf.ToCharArray())
  • ' La première ligne contient les noms de colonnes
  • Dim columnNames() As String = csvLines(0).Split(";"c)
  • ' S'il n'y a aucune colonne ont sort.
  • If columnNames.Length <= 0 Then Return
  • ' Chacune des autres lignes contient un enregistrement
  • For i As Integer = 1 To csvLines.GetUpperBound(0)
  • If csvLines(i) <> "" Then ' Sauter les lignes blanches résultant du split
  • Dim csvFields() As String = csvLines(i).Split(";"c)
  • Dim row As DataRow = dataTable.NewRow()
  • ' Transférer chaque champ dans le nouvel enregistrement.
  • ' Sauter les colonnes qui ne sont pas mappées dans le DataSet
  • For j As Integer = 0 To columnNames.GetUpperBound(0)
  • If csvFields(j) <> "" And dataTable.Columns.Contains(columnNames(j)) Then
  • row(columnNames(j)) = csvFields(j)
  • End If
  • Next j
  • ' L'insertion du nouvel enregistrement peut echouer pour des raisons
  • ' d'intégrité des données. Dans ce cas, on ignore l'echec et on continue
  • Try
  • dataTable.Rows.Add(row)
  • Catch ex As Exception
  • End Try
  • End If ' csvLine(i) <> ""
  • Next i
  • End Sub
  • #End Region
  • #Region " Word "
  • ' Importe les données d'un DataSet depuis un document Word.
  • ' Dans le document source, chaque table est représentée par un tableau.
  • ' La première cellule d'un tableau s'étend sur toute une ligne et contient le nom de la table.
  • ' Les cellules de la deuxième ligne contiennent les noms de colonnes.
  • ' Le reste du tableau contient les données de la table.
  • Public Shared Sub ImportWord(ByVal dataSet As DataSet, ByVal fileName As String)
  • With New Word.ApplicationClass ' Lancer Word en arrière-plan
  • With .Documents.Open(CObj(fileName)) ' Ouvrir le document source
  • For i As Integer = 1 To .Tables.Count ' Parcourir sa collection de tableaux
  • With .Tables(i) ' A chaque tableau, associer un DataTable dans le DataSet
  • Dim tableName As String = TrimNoises(.Cell(1, 1).Range.Text)
  • If dataSet.Tables.Contains(tableName) Then ' Sauter les tables qui ne sont pas mappés dans le DataSet
  • Dim dataTable As DataTable = dataSet.Tables(tableName)
  • For j As Integer = 3 To .Rows.Count
  • Dim dataRow As DataRow = dataTable.NewRow()
  • ' Transférer chaque champ dans le nouvel enregistrement.
  • ' Sauter les colonnes qui ne sont pas mappées dans le DataSet
  • For k As Integer = 1 To .Columns.Count
  • Dim columnName As String = TrimNoises(.Cell(2, k).Range.Text)
  • Dim cellValue As String = TrimNoises(.Cell(j, k).Range.Text)
  • If cellValue <> "" And dataTable.Columns.Contains(columnName) Then
  • dataRow(columnName) = cellValue
  • End If
  • Next k
  • ' L'insertion du nouvel enregistrement peut echouer pour des raisons
  • ' d'intégrité des données. Dans ce cas, on ignore l'echec et on continue
  • Try
  • dataTable.Rows.Add(dataRow)
  • Catch ex As Exception
  • End Try
  • Next j
  • End If
  • End With ' Word.Table
  • Next i
  • .Close() ' Fermer le document
  • End With ' Word.Document
  • .Quit() ' Quitter Word
  • End With ' Word.Application
  • End Sub
  • #End Region
  • #Region " Excel "
  • ' Importe les données d'un DataSet depuis un classeur Excel.
  • ' Dans le document source, chaque table est représentée par une feuille de calcul.
  • ' Les cellules de la première ligne contiennent les noms de colonnes.
  • ' Le reste de la feuille de calcul contient les données de la table.
  • Public Shared Sub ImportExcel(ByVal dataSet As DataSet, ByVal fileName As String)
  • ' Lancer Excel en arrière-plan
  • Dim excelApp As New Excel.ApplicationClass
  • Try
  • ' Ouvrir le classeur fileName
  • Dim workBook As Excel.Workbook = excelApp.Workbooks.Open(fileName)
  • ' Importer chaque feuille de calcul dans le DataTable de même nom
  • For Each worksheet As Excel.Worksheet In workBook.Worksheets
  • If dataSet.Tables.Contains(worksheet.Name) Then
  • ImportExcel(dataSet.Tables(worksheet.Name), worksheet)
  • End If
  • Next
  • Catch ex As System.Runtime.InteropServices.COMException
  • Throw New ApplicationException(ex.Message, ex)
  • Finally
  • ' Quitter Excel
  • excelApp.Quit()
  • End Try
  • End Sub
  • Public Shared Sub ImportExcel(ByVal dataTable As DataTable, ByVal fileName As String)
  • ' Lancer Excel en arrière-plan
  • Dim excelApp As New Excel.ApplicationClass
  • Try
  • ' Ouvrir le classeur fileName
  • Dim workBook As Excel.Workbook = excelApp.Workbooks.Open(fileName)
  • ' Importer la feuille de calcul dans le DataTable de même nom
  • For Each worksheet As Excel.Worksheet In workBook.Worksheets
  • If worksheet.Name = dataTable.TableName Then
  • ImportExcel(dataTable, worksheet)
  • Exit For
  • End If
  • Next
  • Catch ex As System.Runtime.InteropServices.COMException
  • Throw New ApplicationException(ex.Message, ex)
  • Finally
  • ' Quitter Excel
  • excelApp.Quit()
  • End Try
  • End Sub
  • Private Shared Sub ImportExcel(ByVal dataTable As DataTable, ByVal worksheet As Excel.Worksheet)
  • ' Localiser la dernière colonne
  • Dim lastCol As Excel.Range = worksheet.Range("A1").End(Excel.XlDirection.xlToRight)
  • ' Localiser la dernière ligne
  • Dim lastRow As Excel.Range = worksheet.Range("A1").End(Excel.XlDirection.xlDown)
  • ' Extraire toutes les données de la feuille de calcul en une seule opération
  • Dim rangeName As String = GetExcelRange(0, 0, lastRow.Row - 1, lastCol.Column - 1)
  • Dim values As Object(,) = worksheet.Range(rangeName).Value2
  • ' Transférérer les données extraites dans le DataTable
  • For i As Integer = 2 To values.GetUpperBound(0) Step 1
  • Dim newRow As DataRow = dataTable.NewRow()
  • For j As Integer = 1 To values.GetUpperBound(1) Step 1
  • If Nothing Is values(i, j) Then
  • newRow(values(1, j).ToString()) = DBNull.Value
  • Else
  • newRow(values(1, j).ToString()) = values(i, j)
  • End If
  • Next
  • dataTable.Rows.Add(newRow)
  • Next
  • End Sub
  • #End Region
  • #End Region
  • #Region " Méthodes utilitaires "
  • ' Permet d'obtenir le nom d'un cellule Excel à partir de ses coordonnées.
  • ' Par exemple, pour les coordonnées (0, 0) on obtiendrait "A1".
  • ' Le nombre de colonnes ne doit pas dépasser 26, sinon...
  • Private Shared Function GetExcelRange(ByVal rowIndex As Integer, ByVal columnIndex As Integer) As String
  • Return ChrW(columnIndex + 65) & (rowIndex + 1)
  • End Function
  • ' Permet d'obtenir le nom d'une plages de cellules Excel à partir de ses coordonnées.
  • Private Shared Function GetExcelRange(ByVal startRowIndex As Integer, ByVal startColumnIndex As Integer, ByVal endRowIndex As Integer, ByVal endColumnIndex As Integer) As String
  • Return GetExcelRange(startRowIndex, startColumnIndex) & ":" & GetExcelRange(endRowIndex, endColumnIndex)
  • End Function
  • ' Permet de sauter au paragraphe suivant d'un document Word
  • Private Shared Sub SkipToNextParagraph(ByVal range As Word.Range)
  • range.InsertParagraphAfter() ' Ajouter un paragraphe à la suite de la plage en cours
  • range.Collapse(Word.WdCollapseDirection.wdCollapseEnd) ' Réduire la plage à sa fin
  • range.MoveEnd(Word.WdUnits.wdParagraph, 1) ' Sauter au paragraphe suivant
  • End Sub
  • ' Permet de débarrasser une chaîne de caractères d'éventuels symboles indésirables.
  • ' Ces symboles que j'appelle "bruits" entourrent parfois le texte extrait de Word
  • Private Shared Function TrimNoises(ByVal s As String) As String
  • Return s.Trim(ChrW(7), ChrW(13))
  • End Function
  • #End Region
  • End Class
Imports System.IO
Imports Addy.Utilities


'==================================================================================
' Englobe les fonctionnalités d'échange de données avec les applications les plus
' courantes. Gère l'importation et l'exportation du contenu d'un DataSet ADO.NET
' sous l'un des formats suivants: XML, CSV, Document Word et Classeur Excel.
'==================================================================================
Public Class DataExchange

#Region " Constantes "

	Const WORD_MAX_ROWS As Integer = 32767
	Const EXCEL_MAX_ROWS As Integer = 65535
	Const DEFAULT_FIELD_SEPARATOR As Char = ";"c

#End Region

#Region " Export "

#Region " Generique "

    ' Permet d'exporter les données d'un DataSet vers un fichier.
    ' L'extension du nom de fichier permet de déviner le format.
    Public Shared Sub Export(ByVal dataSet As DataSet, ByVal fileName As String)
        Dim ext As String = Path.GetExtension(fileName)
        Select Case ext.ToLower()
            Case ".xml"
                ExportXml(dataSet, fileName)
            Case ".csv"
                ExportCSV(dataSet.Tables(0), fileName)
            Case ".doc"
                ExportWord(dataSet, fileName)
            Case ".xls"
                ExportExcel(dataSet, fileName)
            Case Else
                Throw New InvalidOperationException("Ce format de fichier n'est pas pris en charge")
        End Select
    End Sub

#End Region

#Region " XML "

    ' Exporte les données d'un DataSet vers un document XML
    Public Shared Sub ExportXml(ByVal dataSet As DataSet, ByVal fileName As String)
        dataSet.WriteXml(fileName)
    End Sub

    ' Exporte une plage de données d'un DataTable vers un document XML
    Public Shared Sub ExportXml(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
        ' On crée un DataSet et on y met une copie du DataTable
        Dim dataSet As New dataSet(dataTable.TableName)
        Dim dtClone As dataTable = dataTable.Clone()
        dataSet.Tables.Add(dtClone)

        ' Par la suite, on transfarère une copie des lignes à exporter dans la copie du DataTable
        Dim i As Integer = startIndex
        Dim n As Integer = Math.Min(startIndex + rowCount, dataTable.Rows.Count)

        While i < n
            dtClone.ImportRow(dataTable.Rows(i))
            i += 1
        End While

        ' On termine en enregistrant le tout au format XML
        dataSet.WriteXml(fileName)
    End Sub

    ' Exporte toutes les données d'un DataTable vers un document XML
    Public Shared Sub ExportXml(ByVal dataTable As DataTable, ByVal fileName As String)
        ExportXml(dataTable, fileName, 0, Integer.MaxValue)
    End Sub

#End Region

#Region " CSV "

    ' Exporte une plage de données d'un DataTable vers un fichier texte
    ' Chaque enregistrement sera écrit sur une seule ligne. Un caractère spécial sera
    ' utilisé comme séparatier de champs. Un autre sera utilisé pour entourer les champs.
    Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String, _
            ByVal startIndex As Integer, ByVal rowCount As Integer, ByVal fieldSeparator As Char, _
            ByVal fieldContainer As Char)

        ' Ouvrir un fichier texte en écriture
        Dim csvFile As New StreamWriter(fileName)
        Dim n As Integer = dataTable.Columns.Count

        ' Ecrire les noms de colonnes sur la première ligne en les séparant par des points-virgules
        For j As Integer = 0 To n - 2
			csvFile.Write(DataFormat.QuotedString(dataTable.Columns(j).ColumnName, fieldContainer))
			csvFile.Write(fieldSeparator)
		Next j

		csvFile.WriteLine(DataFormat.QuotedString(dataTable.Columns(n - 1).ColumnName, fieldContainer))

        ' Ecrire chaque enregistrement par la suite en respectant la même logique
        Dim i As Integer = startIndex
        Dim m As Integer = Math.Min(startIndex + rowCount, dataTable.Rows.Count)

        While i < m
            For j As Integer = 0 To n - 2
				csvFile.Write(DataFormat.QuotedString(Convert.ToString(dataTable.Rows(i)(j)), fieldContainer))
				csvFile.Write(fieldSeparator)
			Next j

			csvFile.WriteLine(DataFormat.QuotedString(Convert.ToString(dataTable.Rows(i)(n - 1)), fieldContainer))
            i += 1
        End While

        ' Fermer le fichier
        csvFile.Close()
    End Sub

    ' Une surchage pour laquelle fieldSeparator vaut le poit-virgule tandis que fieldContainer est le caractère nul (donc pas de conteneur de champs)
    Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
        ExportCSV(dataTable, fileName, startIndex, rowCount, DEFAULT_FIELD_SEPARATOR, Char.MinValue)
    End Sub

    ' Une surchage sans borne (on exporte toute la table)
    Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String, ByVal fieldSeparator As Char, ByVal fieldContainer As Char)
        ExportCSV(dataTable, fileName, 0, Integer.MaxValue, fieldSeparator, fieldContainer)
    End Sub

    ' Une surchage sans borne et pour laquelle fieldSeparator vaut le poit-virgule tandis que fieldContainer est le caractère nul
    Public Shared Sub ExportCSV(ByVal dataTable As DataTable, ByVal fileName As String)
        ExportCSV(dataTable, fileName, 0, Integer.MaxValue, DEFAULT_FIELD_SEPARATOR, Char.MinValue)
    End Sub

    ' Exporte les données d'un DataSet vers un ensemble de fichiers texte à valeurs separées par des caractères spéciaux.
    ' Chaque table est exportée vers un fichier distinct. Tous ces fichiers sont regroupés dans le même dossier
    Public Shared Sub ExportCSV(ByVal dataSet As DataSet, ByVal dirName As String, ByVal fieldSeparator As Char, ByVal fieldContainer As Char)
        ' On crée le répertoire du groupe...
        If Not Directory.Exists(dirName) Then
            Directory.CreateDirectory(dirName)
        End If

        ' ...et on exporte chaque jeu d'enregistrements du groupe de données vers un fichier qui porte son nom
        For Each table As DataTable In dataSet.Tables
            ExportCSV(table, Path.Combine(dirName, table.TableName & ".csv"), fieldSeparator, fieldContainer)
        Next
    End Sub

    ' Exporte les données d'un DataSet vers un ensemble de fichiers texte à valeurs separées par des point-virgules.
    Public Shared Sub ExportCSV(ByVal dataSet As DataSet, ByVal dirName As String)
        ExportCSV(dataSet, dirName, DEFAULT_FIELD_SEPARATOR, Char.MinValue)
    End Sub

#End Region

#Region " Word "

    ' Exporte les données d'un DataSet vers un document Word
    Public Shared Sub ExportWord(ByVal dataSet As DataSet, ByVal fileName As String)
        ' Lancer Word en arrière-plan
        Dim wordApp As New Word.ApplicationClass

        Try
            ' Créer un nouveau document
            Dim document As Word.Document = wordApp.Documents.Add()

            ' Définir Arial (taille 10) comme police par défaut du document
            Dim range As Word.Range = document.Content
            range.Font.Name = "Arial"
            range.Font.Size = 10

            ' Exporter chaque DataTable dans un tableau spécifique
            For Each dataTable As dataTable In dataSet.Tables
                ExportWord(dataTable, document, range, 0, WORD_MAX_ROWS)
                SkipToNextParagraph(range)
            Next

            ' Enregistrer le document sous le chemin spécifié
			document.SaveAs(CObj(fileName))
        Catch ex As System.Runtime.InteropServices.COMException
            Throw New ApplicationException(ex.Message, ex)
        Finally
            ' Quitter Word
            wordApp.Quit()
        End Try
    End Sub

    ' Exporte une plage de données d'un DataTable vers un document Word
    Public Shared Sub ExportWord(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
        ' Lancer Word en arrière-plan
        Dim wordApp As New Word.ApplicationClass

        Try
            ' Créer un nouveau document
            Dim document As Word.Document = wordApp.Documents.Add()

            ' Définir Arial (taille 10) comme police par défaut du document
            Dim range As Word.Range = document.Content
            range.Font.Name = "Arial"
            range.Font.Size = 10

            ' Exporter la plage de DataRows dans un tableau spécifique
            ExportWord(dataTable, document, range, startIndex, rowCount)

            ' Enregistrer le document sous le chemin spécifié
			document.SaveAs(CObj(fileName))
        Catch ex As System.Runtime.InteropServices.COMException
            Throw New ApplicationException(ex.Message, ex)
        Finally
            ' Quitter Word
            wordApp.Quit()
        End Try
    End Sub

    ' Exporte toutes les données d'un DataTable vers un document Word
    Public Shared Sub ExportWord(ByVal dataTable As DataTable, ByVal fileName As String)
        ExportWord(dataTable, fileName, 0, WORD_MAX_ROWS)
    End Sub

    ' Définit la logique d'exportation vers Word à proprement parler
    Private Shared Sub ExportWord(ByVal dataTable As DataTable, ByVal document As Word.Document, ByVal range As Word.Range, ByVal startIndex As Integer, ByVal rowCount As Integer)
        Dim m As Integer = Math.Min(rowCount, WORD_MAX_ROWS - 2)
        Dim n As Integer = dataTable.Columns.Count

        With document.Tables.Add(range, m + 2, n) ' Créer un tableau dans la plage "range"
            .Cell(1, 1).Merge(.Cell(1, n))  ' Fusionner toutes les cellules de la première ligne du tableau
            With .Cell(1, 1).Range          ' Mettre l'unique cellule de cette ligne en forme et lui affecter le nom du DataTable
                .Shading.BackgroundPatternColor = Word.WdColor.wdColorGray15
                .ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter
                .Font.Size = 16
                .Bold = True
                .Text = dataTable.TableName
            End With ' Cell(1, 1).Range

            ' Les cellules de la deuxième ligne contiendront les noms de colonnes
            For i As Integer = 0 To n - 1
                With .Cell(2, i + 1).Range
                    .ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter
                    .Bold = True
                    .Text = dataTable.Columns(i).ColumnName
                End With ' Cell(2, i + 1).Range
            Next i

            ' Les autres cellules du tableau contiendront les valeurs du DataTable
            Dim k As Integer = startIndex, l As Integer = 3
            Dim m2 As Integer = Math.Min(startIndex + m, dataTable.Rows.Count)

            While k < m2
                For j As Integer = 0 To n - 1
                    .Cell(l, j + 1).Range.Text = Convert.ToString(dataTable.Rows(k)(j))
                Next j
                l += 1
                k += 1
            End While

            .AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitContent)       ' Ajuster la taille du tableau à son contenu
            .Borders.OutsideLineStyle = Word.WdLineStyle.wdLineStyleSingle  ' Encadrer le tableau à l'exterieur...
            .Borders.InsideLineStyle = Word.WdLineStyle.wdLineStyleSingle   ' ...et à l'intérieur (afficher le quadrillage)
        End With ' Word.Tables.Add
    End Sub

#End Region

#Region " Excel "

    ' Exporte les données d'un DataSet vers un classeur Excel
    Public Shared Sub ExportExcel(ByVal dataSet As DataSet, ByVal fileName As String)
        ' Lancer Excel en arrière-plan
        Dim excelApp As New Excel.ApplicationClass

        Try
            Dim workBook As Excel.Workbook = excelApp.Workbooks.Add()

            ' Avant de continuer, on enregistre les feuilles par défaut créées
            ' dans le classeur afin de pouvoir les supprimer plus tard
            Dim defaultSheets As New ArrayList
            For i As Integer = 1 To workBook.Sheets.Count
                defaultSheets.Add(workBook.Sheets(i))
            Next

            ' On parcourre la collection de DataTables du DataSet et
            ' on crée une feuille de calcul pour chacun
            For Each table As DataTable In dataSet.Tables
                ExportExcel(table, workBook, 0, Integer.MaxValue)
            Next

            ' Supprimer les feuilles par défaut (Feuil1...Feuil3 ou Sheet1...Sheet3 ou...)
            ' Il est impossible de les supprimer toutes au départ car un classeur Excel
            ' doit toujours conténir une feuille au moins
            For Each worksheet As Excel.Worksheet In defaultSheets
                worksheet.Delete()
            Next

            ' Sauvegarder le classeur
            workBook.SaveAs(fileName)
        Catch ex As System.Runtime.InteropServices.COMException
            Throw New ApplicationException(ex.Message, ex)
        Finally
            ' Quitter Excel
            excelApp.Quit()
        End Try
    End Sub

    ' Exporte une plage de données de DataTable vers un classeur Excel
    Public Shared Sub ExportExcel(ByVal dataTable As DataTable, ByVal fileName As String, ByVal startIndex As Integer, ByVal rowCount As Integer)
        ' Lancer Excel en arrière-plan
        Dim excelApp As New Excel.ApplicationClass

        Try
            Dim workBook As Excel.Workbook = excelApp.Workbooks.Add()

            ' Avant de continuer, on enregistre les feuilles par défaut créées
            ' dans le classeur afin de pouvoir les supprimer plus tard
            Dim defaultSheets As New ArrayList
            For i As Integer = 1 To workBook.Sheets.Count
                defaultSheets.Add(workBook.Sheets(i))
            Next

            ' On crée une feuille de calcul pour le DataTable
            ExportExcel(dataTable, workBook, startIndex, rowCount)

            ' Supprimer les feuilles par défaut (Feuil1...Feuil3 ou Sheet1...Sheet3 ou...)
            ' Il est impossible de les supprimer toutes au départ car un classeur Excel
            ' doit toujours conténir une feuille au moins
            For Each worksheet As Excel.Worksheet In defaultSheets
                worksheet.Delete()
            Next

            ' Sauvegarder le classeur
            workBook.