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?
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.