Export des données sql server 2000 vers access : utilisation et execution d'un lot dts

Description

Il existe de nombreux exemple d'export de données d'une application web vers un fichier Excel.
http://www.aspfr.com/code.aspx?ID=8935
On utilise en général le flux HTML avec comme ContentType = "application/vnd.ms-excel", l'autre méthode étant d'utiliser l'automation OLE, attention toute fois aux performances dans ce dernier cas.

Mais comment faire pour exporter vers Access ? On ne peut le faire, à ma connaisance, via un flux HTML.
En revanche on peut dans le cas de SQL Server faire appel aux lots DTS et appeller ces lots dans une application ASP.NET
Pour celà il faut utiliser un composant COM "Microsoft DTSPackage Object Library" qu'il faut référencer dans votre application ASP.NET
Le mode d'authentification doit être celle de SQL Server et non Windows donc pas de "Integrated Security=SSPI" dans la chaine de connection.

La démarche : (Format 2000 du fichier Access)

1° Conserver le système relationnel des données à exporter
Dans ce cas il faut préalablement créer un fichier modèle sur le server (model.mdb) avec les tables d'origines vides mais liées entre elles.

1°bis Si pas conservation du système relationnel des données à exporter
Dans ce cas on utilise un fichier modèle (model.mdb) totalement vide que l'on crée préalablement ou dynamiquement dans l'application ASP.NET en utilisant le composant COM ADOX "Microsoft ADO Ext. 2.8 for DDL and Security" mais pourquoi se compliquer ? Autant le créer avant et si on a besoin de le copier et de le renommer on utilisera les class .NET du System.IO

Le code de création dynamique d'un fichier Access est dans ce cas :
Imports ADOX
'Création d'un fichier Access
'path = "D:\TempFile\model.mdb"
Public Shared Function NewMDB(ByVal path As String) As String
Dim message As String = "Fichier Access créé correctement"
Try
Dim cat As ADOX.Catalog = New ADOX.Catalog
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & path & _
"Jet OLEDB:Engine Type=5")
cat.ActiveConnection.close()
cat = Nothing
Catch exc As System.Runtime.InteropServices.COMException
message = exc.Message()
Catch exc As Exception
message = exc.Message()
Finally
NewMDB = message
End Try
End Function

2° Création du Lot DTS
Inconvénient : le nom du fichier modèle "model.mdb" doit être connu à l'avance, il est peut-être possible d'utiliser les variables globales des lots DTS et de les passer en paramètre dans le code mais je n'ai pas trouvé la méthode
cf impr écran dans le doc dts.doc

3° Execution du lot DTS dans l'application ASP.NET
On peut se limiter à ce code :

Imports System.Runtime.InteropServices
Imports DTS

'Nom du lot = package = "ExportAccess"
Public Class ExportDTS

Function Execute(ByVal package As String) As String

Dim pkg As DTS.Package
Dim message As String = "Export ok"

Try
pkg = New DTS.Package
pkg.LoadFromSQLServer("Nom du server", "User", "Password", _
DTSSQLServerStorageFlags.DTSSQLStgFlag_Default, _
"", "", "", package, Nothing)
pkg.Execute()
pkg.UnInitialize()
pkg = Nothing
Catch exc As System.Runtime.InteropServices.COMException
message = exc.Message()
Catch exc As Exception
message = exc.Message()
Finally
End Try

Execute = message

End Function

En revanche l'utilisation de la class PackageEventsSink sert à controler le bon déroulement de l'execution du lot DTS. Je ne maitrise malheureusement pas sa réelle utilité.
cf. 321525 HOW TO: Use DTS Package Events in Visual Basic .NET
http://support.microsoft.com/?id=321525

Source / Exemple :


Imports System.Runtime.InteropServices
Imports DTS

'Nom du lot = package = "ExportAccess"
Public Class ExportDTS

	Function Execute(ByVal package As String) As String

		Dim pkg As DTS.Package
		Dim message As String = "Export ok"

		Try
			pkg = New DTS.Package
			'Debut - set up events sink
			Dim cpContainer As UCOMIConnectionPointContainer
			cpContainer = CType(pkg, UCOMIConnectionPointContainer)
			Dim cpPoint As UCOMIConnectionPoint
			Dim PES As PackageEventsSink = New PackageEventsSink
			Dim guid As Guid = _
			 New Guid("10020605-EB1C-11CF-AE6E-00AA004A34D5")
			cpContainer.FindConnectionPoint(guid, cpPoint)
			Dim intCookie As Integer
			cpPoint.Advise(PES, intCookie)
			'Fin - set up events sink
			pkg.LoadFromSQLServer("Nom du server", "User", "Password", _
			 DTSSQLServerStorageFlags.DTSSQLStgFlag_Default, _
			 "", "", "", package, Nothing)
			pkg.Execute()
			pkg.UnInitialize()
			pkg = Nothing
			cpPoint.Unadvise(intCookie)
			cpPoint = Nothing
			cpContainer = Nothing
			PES = Nothing
		Catch exc As System.Runtime.InteropServices.COMException
			message = exc.Message()
		Catch exc As Exception
			message = exc.Message()
		Finally
		End Try

		Execute = message

    End Function

End Class

'Permet de suivre l'execution du lot DTS
Public Class PackageEventsSink
    Implements DTS.PackageEvents

    Overridable Overloads Sub OnError(ByVal EventSource As String, _
            ByVal ErrorCode As Integer, ByVal Source As String, _
            ByVal Description As String, ByVal HelpFile As String, _
            ByVal HelpContext As Integer, ByVal IDofInterfaceWithError As String, _
            ByRef pbCancel As Boolean) Implements DTS.PackageEvents.OnError
        Console.WriteLine(" OnError in {0}; ErrorCode = {1}, Source = {2}," & _
            " Description = {3}", EventSource, ErrorCode, Source, Description)
    End Sub
    Overridable Overloads Sub OnFinish(ByVal EventSource As String) _
            Implements DTS.PackageEvents.OnFinish
        Console.WriteLine(" OnFinish in {0}", EventSource)
    End Sub
    Overridable Overloads Sub OnProgress(ByVal EventSource As String, _
            ByVal ProgressDescription As String, ByVal PercentComplete As Integer, _
            ByVal ProgressCountLow As Integer, ByVal ProgressCountHigh As Integer) _
            Implements DTS.PackageEvents.OnProgress
        Console.WriteLine(" OnProgress in {0}; ProgressDescription = {1}", _
            EventSource, ProgressDescription)
    End Sub
    Overridable Overloads Sub OnQueryCancel(ByVal EventSource As String, _
            ByRef pbCancel As Boolean) Implements DTS.PackageEvents.OnQueryCancel
        If EventSource.Length > 0 Then
            Console.WriteLine(" OnQueryCancel in {0}; pbCancel = {1}", _
                EventSource, pbCancel.ToString)
        Else
            Console.WriteLine(" OnQueryCancel; pbCancel = {0}", pbCancel.ToString)
        End If
        pbCancel = False
    End Sub
    Overridable Overloads Sub OnStart(ByVal EventSource As String) _
            Implements DTS.PackageEvents.OnStart
        Console.WriteLine(" OnStart in {0}", EventSource)
    End Sub

End Class

'-----------------------------------------------------------
'Exemple d'utilisation de ces class dans un fichier ASPX.VB
'Penser à créer le control hyperlink dans l'aspx nommer "HL_Export"
'---------------------------------------------------------------------------------------

Imports System.IO

Public Class export
    Inherits System.Web.UI.Page

'Execution de l'export via un lot DTS
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

		'Nom du fichier final
		Dim final As String = "final.mdb"

		'Nom du fichier d'export temporaire
		Dim file As String = "model.mdb"
		
		'Execution du lot DTS
		Dim export As New ExportDTS
		export.Execute("ExportAccess"))
		
		'Renommage du fichier d'export
                                File.copy("D:\TempFile\" & file, D:\tempFile\" & final)
                                File.delete("D:\tempFile\" & file)

		'Téléchargement du fichier
		HL_Export.NavigateUrl = "http://localhost/TempFile/" & final
		HL_Export.Text = "Télécharger"

End Sub

End Class

Conclusion :


Voilà j'espère que c'est assez clair :)

Certains ne manqueront pas de faire remarquer à juste titre que l'utilisation des lots DTS n'est utile qu'en cas d'utilisation de SQL Server. Alors qu'en est il avec Oracle ou tout autre base de données ?
Peut être apporterez vous une réponse.
Une piste cependant est l'utilisation dans le code des "insert into" via ODBC :
SELECT * INTO [AccTable] FROM [odbc;driver={ServerBDD};server=MYSERVER;database=MYDB;uid=myuser;pwd=mypass].[SQLTable]
Mais je n'ai pas testé cette approche qui me parait un peu lourde

Amicalement et bon coding

Denis

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.