Importer/exporter facilement vos données sous différents formats

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 / Exemple :


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

Conclusion :


Cette source a été écrite et testée sur une machine équipée de Office 2003. Je ne sais pas si elle se comporte autrement avec d'autres versions de la suite. Vous m'en direz plus. Par ailleurs, l'echange de données avec Word est assez lent. Bon mais ça dépend de votre équipement n'est-ce pas?

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.