Pour pouvoir alimenter ce sas, nous avons construit une batterie de rapports Business Objects XI R2 (fichiers .rep) dont la section principale est précisément le code qui nous servira de clé de découpage. Nous avons ensuite ajouté une macro qui se déclenche après le rafraichissement et qui va se charger de parcourir le fournisseur de données du rapport qui contient la liste des codes sur lesquels appuyer le découpage.
La macro présentée ci joint part du postula qu'il existe dans le document BO un fournisseur de données sur lequel on va s'appuyer pour générer autant de document PDF qu'il y a d'entrées distinctes d'une variable de ce fournisseur.
L'exemple suivant est celui d'un rapport de suivi budgétaire pour lequel on génère autant de PDF qu'il y a de comptes présents dans les tableaux de bord. Dans cet exemple, les documents contiennent un fournisseur de données "Comptes" (Constante DATA_PROVIDER) dont on va extraire la variable "Compte" (Constante VAR_NAME).
Le principe est ensuite de récupérer la liste des comptes différents puis d'appliquer un filtre global sur la valeur de ce filtre et d'enregistrer le résultat au format PDF avec comme nom "xxxx.pdf" ou "xxxx" est le n° du compte considéré.
La macro s'appuie sur des variables d'environnement :
- FICHIERS_LOG pour déterminer le répertoire dans lequel sont écrits les logs
- FICHIERS_PDF pour déposer les fichiers PDF
Enfin, à la fin du traitement, le système envoie un mail à l'aide de "Postie.exe" pour donner la liste des fichiers générés.
Option Explicit
Dim sLogFile, sLogMsg As String
Dim FilePath, LogFilePath As String
Dim fs As Variant
Const VAR_NAME = "Compte"
Const DATA_PROVIDER = "Comptes"
Const BATCH_FILE = "myBatchFile.bat"
#Const DEBUG_MODE = 0
Private Sub Document_AfterRefresh()
'Déclaration des variables
Dim doc As Document
Dim dp As DataProvider
Dim cols As Columns
Dim col As Column
Dim rep As Report
Dim Compte As String
Dim FullVarName As String
Dim i As Integer
Dim nb_file, nb_pending As Integer
Dim FileName As String
Dim PrevFileName As String
Dim OutputFile
On Error GoTo ErrorHandler
Set fs = CreateObject("Scripting.FileSystemObject")
' Récupération de la valeur de la variable d'environnement FICHIERS_LOG
' pour générer le chemin d'accès au fichier de log
LogFilePath = Environ$("FICHIERS_LOG")
If LogFilePath = "" Then
LogFilePath = "C:\TEMP\FICHIERS_LOG"
End If
' S'il n'y a pas de "\" à la fin, on l'ajoute
If Right(LogFilePath, 1) <> "\" Then
LogFilePath = LogFilePath + "\"
End If
' Création du fichier de log
sLogFile = LogFilePath & "logfile_" & Format(Now, "YYYYMMDD_HHMM") & ".log"
fs.CreateTextFile (sLogFile)
' Récupération de la valeur de la variable d'environnement FICHIERS_PDF
' pour générer le chemin d'accès aux fichiers PDF générés par BO
FilePath = Environ$("FICHIERS_PDF")
If FilePath = "" Then
FilePath = "C:\TEMP\FICHIERS_PDF"
End If
' S'il n y a pas de "\" à la fin, on l'ajoute
If Right(FilePath, 1) <> "\" Then
FilePath = FilePath + "\"
End If
#If DEBUG_MODE Then
Dim vars As Variables
Set vars = Application.Variables
Call LogMessage("DEBUG - Listes des variables d'environnement :")
Call LogMessage("DEBUG ----------------------------------------")
For i = 1 To vars.Count
Call LogMessage("DEBUG - " & vars.Item(i).Name & " = " & vars.Item(i).Value)
Next
Call LogMessage("DEBUG ----------------------------------------" & vbCrLf)
Call LogMessage("DEBUG - Environ$(FICHIERS_LOG)=" & Environ$("FICHIERS_LOG"))
Call LogMessage("DEBUG - LogFilePath=" & LogFilePath)
Call LogMessage("DEBUG - Environ$(FICHIERS_PDF)=" & Environ$("FICHIERS_PDF"))
Call LogMessage("DEBUG - FilePath=" & FilePath)
#End If
' Vérification que le répertoire de dépôt existe
' si non, essayer de le créer
If Not fs.FolderExists(FilePath) Then
Call LogMessage("INFO - Création du répertoire " & FilePath)fs.CreateFolder (FilePath)
End If
' Pour que cette macro fonctionne, on suppose que le document contienne
' un fournisseur de données dont le nom est défini dans la constante DATA_PROVIDER
' qui est supposé contenir la liste des valeurs à analyser dans un objet
' dont le nom est défini dans la constante VAR_NAME
Set doc = Application.Documents.Item(1)
Set dp = doc.DataProviders(DATA_PROVIDER)
Set cols = dp.Columns
Set col = cols(VAR_NAME)
Set rep = doc.Reports.Item(1)
FullVarName = VAR_NAME & "(" & DATA_PROVIDER & ")"
#If DEBUG_MODE Then
Call LogMessage("DEBUG - doc=" & doc.Name)
Call LogMessage("DEBUG - dp=" & dp.Name)
Call LogMessage("DEBUG - cols (nb)=" & CStr(cols.Count))
Call LogMessage("DEBUG - col (nb)=" & CStr(col.Count))
Call LogMessage("DEBUG - rep=" & rep.Name)
Call LogMessage("DEBUG - FullVarName=" & FullVarName)
#End If
' rep.Activate => ne fonctionne pas en InfoView
' Test de présence de fichiers correspondant aux mêmes comptes
' Dans le cas où il y en a déjà, on arrête le traitement
Call LogMessage("INFO - Contrôle des fichiers encore en attente :")
Call LogMessage("INFO -------------------------------------------")
nb_file = 0
nb_pending = 0
FileName = Dir(FilePath & "*.pdf")
Do While FileName <> ""
' Dès qu'on trouve un fichier en attente, on ajoute 1
' au nombre de fichier en attente
nb_file = nb_file + 1
nb_pending = nb_pending + 1
Call LogMessage("WARNING - Le fichier " & FileName & " est en attente d'intégration.")
i = InStr(1, FileName, ".pdf")
Compte = Left(FileName, i - 1)
For i = 1 To col.Count
If col.Item(i) = Compte Then
Call LogMessage("INFO - Le fichier " & FileName & " sera écrasé.")
' Si ce fichier est concerné par le régénération
' on retire 1 au nombre de fichier en attente
' car il sera remplacé par un nouveau fichier
nb_file = nb_file - 1
' Et on force la sortie de la boucle "for"
i = col.Count + 1
End If
Next
FileName = Dir ' passe au fichier suivant.
Loop
' Si le nombre de fichier en attente (et qui ne sont pas remplacé par le traitement en cours)
' n'est pas nul, on averti l'utilisateur qu'il doit d'abord vider le répertoire d'attente
' avant de lancer une régénération de fichiers PDF
If nb_file > 0 Then
Call LogMessage("WARNING - Il existe " & CStr(nb_pending) & " fichiers en attente de publication " _
& "parmi lesquels, " & CStr(nb_file) & " ne seront pas régénérés par ce traitement." & vbCrLf _
& "Vous devez d'abord intégrer les publications avant de générer de nouveaux fichiers, " _
& "ou demander aux administrateurs de supprimer ces fichiers." & vbCrLf _
& vbCrLf _
& "Arrêt du traitement.")
Call LogMessage("INFO - Fin du Contrôle des fichiers en attente")
Call LogMessage("INFO -------------------------------------------" & vbCrLf)
CreateBatchFile doc.Name, sLogFile
Shell LogFilePath & BATCH_FILE
Exit Sub
End If
If nb_pending > 0 Then
Call LogMessage("WARNING - Les " & CStr(nb_pending) & " fichiers en attente de publication " _
& "seront tous régénérés par ce traitement." & vbCrLf)
Else
Call LogMessage("INFO - Aucun fichier en attente")
End If
Call LogMessage("INFO - Fin du Contrôle des fichiers en attente")
Call LogMessage("INFO -------------------------------------------" & vbCrLf)
PrevFileName = "x"
nb_file = 0
For i = 1 To col.Count
Compte = col.Item(i)
FileName = FilePath & Compte & ".pdf"
#If DEBUG_MODE Then
Call LogMessage("DEBUG - Compte=" & Compte)
Call LogMessage("DEBUG - FileName=" & FileName)
#End If
' Il se peut qu'il y ait plusieurs lignes pour le même compte dans le fournisseur de données
' Dans ce cas, on ne régénère pas fichier
If FileName <> PrevFileName Then
rep.ForceCompute
Call rep.AddComplexFilter(FullVarName, "=<" & FullVarName & ">=""" + Compte + """")
rep.ExportAsPDF (FileName)
Set OutputFile = fs.GetFile(FileName)
nb_file = nb_file + 1
Call LogMessage("INFO - Creation du PDF " & Compte & ".pdf" & " de taille " & OutputFile.Size & " octets")
End If
PrevFileName = FileName
Next
Call rep.AddComplexFilter(FullVarName, "=1=1")
Close
Call LogMessage("INFO - Fin du traitement. " & CStr(nb_file) & " document(s) généré(s).")
CreateBatchFile doc.Name, sLogFile
Shell LogFilePath & BATCH_FILE
Exit Sub
ErrorHandler:
sLogMsg = "ERROR - " & Err.Number & " - " & Err.Description
Call LogMessage(sLogMsg)
Resume Next
End Sub
Sub LogMessage(sLogMsg)
Dim msgText As String
Dim nFile As Integer
nFile = FreeFile
Open sLogFile For Append As #nFile< msgText = Format(Now, "mm/dd/yy hh:mm:ss") & " - " & sLogMsg
Print #nFile, msgText
Close #nFile
End Sub
Sub CreateBatchFile(DocName, LogFile)
Dim batFile
Dim nFile As Integer
batFile = LogFilePath & BATCH_FILE
nFile = FreeFile
If fs.FileExists(batFile) Then
fs.DeleteFile (batFile)
End If
fs.CreateTextFile (batFile)
Open batFile For Append As #nFile
Print #nFile, LogFilePath & "postie " _
& " -host:SNMP" _
& " -from:BusinessObjects@me.com" _
& " -tolist:" & LogFilePath & "myMailingList.lst" _
& " -s:" & Chr(34) & "Creation des PDF pour " & DocName & Chr(34) _
& " -msg:" & Chr(34) & "Si un fichier est a 0 octet, appeler les administrateurs" & Chr(34) _
& " -file:" & LogFile _
& vbCrLf
Close
End Sub
Aucun commentaire:
Enregistrer un commentaire