Option Explicit
Dim wb As Excel.Workbook
Dim sh As Excel.Worksheet
Dim i As Long, j As Long
Private rst As New ADODB.Recordset
Private OpOk As Boolean
Public Sub change_filegl()
'Macro permettant de choisir le chemin d'accès au fichier de dépouillement GL
'Le chemin complet vers le fichier est alors inscrit en path_filegl pour être traité avec la macro SAISIE
'Theoriquement, feuille OpéJour, cellule C3
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
If .Show = -1 Then
If .SelectedItems.Count <> 1 Then If MsgBox("Choisir le fichier GL !", vbCritical) = vbOK Then Exit Sub
ThisWorkbook.Sheets("OpéJour").[path_filegl].Value = .SelectedItems.Item(1)
Else
If .SelectedItems.Count < 1 Then Exit Sub
End If
End With
Set fd = Nothing
ThisWorkbook.Sheets("OpéJour").[path_filegl].Select
End Sub
Public Sub saisie(Optional StartAtTwo As Boolean = False)
'Importe les données provenant de GL
'Nécéssite eventuellement l'execution de change_filegl() au préalable
'Ouvre le fichier dont l'adresse est recuperée par change_filegl() et copie la liste des opérations
'Verifie ensuite s'il y a des valeurs qui ne sont pas encore suivies dans pose
Dim filegl As Object
Set filegl = CreateObject("scripting.filesystemobject")
Dim wbgl As Excel.Workbook
Set wb = ThisWorkbook
Set sh = wb.Sheets("OpéJour")
Dim pathgl As String
pathgl = sh.[path_filegl].Value
OpOk = False 'Pour la verification de la recopie des opérations
'Verification étape (si insertion de nouvelles valeurs)
If StartAtTwo Then GoTo step2
'Verification de l'existence du fichier GL
If Not filegl.fileexists(sh.[path_filegl]) Then
sh.Select
sh.[path_filegl].Select
MsgBox ("Le fichier " & pathgl & " ne semble pas exister." & Chr(13) & "Verifier l'adresse")
Exit Sub
End If
'Synthèse pour spreads
With wb.Sheets("SynthèseJour")
.[Synth_area_SpdMoy].Copy
.[Synth_area_SpdPrec].PasteSpecial Paste:=xlValues
Application.CutCopyMode = False
End With
'Preparation de la feuille OpéJour
With sh
.Select
.Unprotect
.[Op_area_saisie].ClearContents
End With
'Ouverture et copie des données
Workbooks.Open (pathgl)
Set wbgl = ActiveWorkbook
wbgl.ActiveSheet.Range("G3").Select
If Selection.Value <> "" Then
Range(Selection, Selection.End(xlToRight)).Select
If Range("G4") <> "" Then Range(Selection, Selection.End(xlDown)).Select
End If
Selection.Copy
With sh
.Activate
.[Op_area_saisie].Cells(1, 1).PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
.[Op_area_saisie].Cells(1, 1).Select
End With
Application.CutCopyMode = False
'Verification de l'existence des valeurs traitées dans pose
wbgl.Close
Set wbgl = Nothing
If check_newvals(True) <> 0 Then
While Not OpOk
check_newvals (True)
Wend
Exit Sub
End If
step2:
CopyOp
GoTo flush
err:
sh.[Op_area_saisie].ClearContents
flush:
wb.Activate
sh.Protect
wb.Sheets("Stock").Activate
Set sh = Nothing
Set filegl = Nothing
End Sub
Public Sub CopyOp()
'Recopie Opé GL retraitées par les op annulées
'Executé après Insertion/Sortie de valeurs
sh.Select
With sh.[Op_liste]
sh.Range(.Cells(5, 2), .Cells(254, 3)).Copy
sh.Range(.Cells(5, 4), .Cells(254, 5)).PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End With
OpOk = True
End Sub
Public Sub vider_position(ByVal isin As String, line As Integer, Optional bOp As Boolean = 1, Optional bOpJour As Boolean = 1, Optional bAuto As Boolean = 0, Optional ancien_typefut As String = "")
Dim str As String, coln As String, Histo As Range, row As Long
Dim tmp(0, 8) As Variant
Set wb = ThisWorkbook
Set sh = wb.Sheets("OpéJour")
tmp(0, 0) = isin
If ancien_typefut = "" Then ancien_typefut = sh.[Op_liste].Cells(line + 4, 6)
'Annuler opérations précédentes
If bOpJour And CLng(Ventes.lTitresJ) <> 0 Then
tmp(0, 1) = CLng(Ventes.lTitresJ)
tmp(0, 2) = CDbl(Ventes.lPrixJ)
'Inscrit l'annulation de l'opération, pour eviter qu'elle soit reprise en compte à la prochaine saisie GL
With sh.[Op_annul]
row = sh.Cells(260, .Column).End(xlUp).row + 1
sh.Range(sh.Cells(row, .Column), sh.Cells(row, .Column + 2)) = tmp
End With
'Vide qte et prix
sh.[Op_liste].Cells(line + 4, 4) = 0
sh.[Op_liste].Cells(line + 4, 5) = 0
sh.Range(sh.[Op_liste].Cells(line + 4, 7), sh.[Op_liste].Cells(line + 4, 10)).ClearContents
End If
'Vider la position
Set Histo = wb.Sheets("Data").[histo_j1]
tmp(0, 1) = 0
tmp(0, 2) = 0
tmp(0, 3) = ancien_typefut 'type_fut
'Opérations
If (bOp = True Or bAuto = True) And Histo.Cells(line + 2, 1) <> 0 Then
If bAuto Then
tmp(0, 1) = -Histo.Cells(line + 2, 1)
Else
tmp(0, 1) = -CLng(Ventes.tTitresV) 'quantite
End If
tmp(0, 2) = Histo.Cells(line + 2, 2) 'prix
str = str & Chr(13) & tmp(0, 1) & " titres à " & tmp(0, 2)
End If
'Futures
If (CDbl(Ventes.tEurexV) <> 0 Or CDbl(Ventes.tSwapnotesV) <> 0 Or bAuto = True) Then
If bAuto Then
tmp(0, 4) = -Histo.Cells(line + 2, 5)
tmp(0, 6) = -Histo.Cells(line + 2, 7)
Else
tmp(0, 4) = -CDbl(Ventes.tEurexV)
tmp(0, 6) = -CDbl(Ventes.tSwapnotesV)
End If
tmp(0, 5) = Histo.Cells(line + 2, 6)
tmp(0, 7) = Histo.Cells(line + 2, 8)
str = str & Chr(13) & tmp(0, 4) & " " & tmp(0, 3) & " à " & tmp(0, 5)
str = str & Chr(13) & tmp(0, 6) & " swapnotes à " & tmp(0, 7)
End If
'Information sur la quantité et le type de future à vendre pour compenser la mise à zero de la couverture
If bAuto Then str = str & Chr(13) & Chr(13) & "A ajouter dans dépou89222 : " & -tmp(0, 1) & " titres à " & Round(wb.Sheets("Data").Cells(line + 9, RechercheNumCol("PxRevient", 9, wb.Sheets("Data"), 1)), 2)
'Vidage effectif
If (CLng(tmp(0, 1)) <> 0 And bOp = True) Or ((CDbl(tmp(0, 4)) <> 0 Or CDbl(tmp(0, 6)) <> 0)) Then
str = "Opérations réalisées : " & isin & Chr(13) & str
With sh.[Op_vidage]
row = sh.Cells(260, .Column).End(xlUp).row + 1
sh.Range(sh.Cells(row, .Column), sh.Cells(row, .Column + 7)) = tmp
End With
Set sh = wb.Sheets("SynthèseJour")
With sh.[Ventes]
If Not bAuto Then
row = sh.Cells(260, .Column).End(xlUp).row + 1
tmp(0, 1) = CLng(Ventes.tQuantite)
tmp(0, 2) = CDbl(Ventes.lPxRev)
tmp(0, 3) = CDbl(Ventes.lSpRev)
tmp(0, 4) = CDbl(Ventes.tPrix)
tmp(0, 5) = CDbl(Ventes.tSpasw)
If Ventes.tSociete <> "Ou saisie manuelle..." Then tmp(0, 6) = Ventes.tSociete Else tmp(0, 6) = "-"
If Ventes.tClient <> "Ou saisie manuelle..." Then tmp(0, 7) = Ventes.tClient Else tmp(0, 7) = "-"
tmp(0, 8) = Now()
sh.Range(sh.Cells(row, .Column), sh.Cells(row, .Column + 8)) = tmp
End If
End With
MsgBox str, vbInformation
End If
Set sh = Nothing
Set wb = Nothing
End Sub
Public Function update_opjour(Optional ByVal UpHisto As Boolean = True) As Boolean
'Update des opérations du jour vers access
'Vide la précédente table temporaire et la rempli à nouveau avec les opérations
Set wb = ThisWorkbook
Set sh = wb.Sheets("OpéJour")
Dim rstv As New ADODB.Recordset
ReInitErrors
'Parametrage formulaire & Verification des cours des futures
Dim curprixfut As Double, curprixsn As Double, Errcours As Integer
Dim strErr As String
' With HistoAccess
' .StatusBar.Panels(1).Text = "Verification cours futures"
' .ProgressBar.max = 259
' .MultiPage1.Value = 0
' .MultiPage1.Style = fmTabStyleNone
' If UpHisto Then
' .Et_lTitre.Caption = "Execution : Update des opérations du jour"
' .Et_l1.Caption = "Verification des cours des futures..."
' .Et_l2.Caption = "Enregistrement des positions vidées..."
' .Et_l3.Caption = "Enregistrement des opérations..."
' .Et_l4.Caption = "Mise à jour historique pour Konzult..."
' .Et_l5.Caption = "Enregistrement des résultats..."
' .Et_l6.Caption = "Enregistrement des coupons..."
' .Et_l7.Caption = "Verification des erreurs..."
' HistoAccess.Et_btnClose.Enabled = False
' .Show
' End If
' End With
With sh.[Op_liste]
For i = 5 To 264
' HistoAccess.ProgressBar.Value = i - 5
If .Cells(i, 1).Value <> "" Then
' HistoAccess.StatusBar.Panels(1).Text = "Verification cours futures - " & .Cells(i, 1)
' HistoAccess.Repaint
Select Case .Cells(i, 6).Value
Case "BUND"
curprixfut = sh.[CoursBund].Value
curprixsn = sh.[CoursSn10].Value
Case "BOBL"
curprixfut = sh.[CoursBobl].Value
curprixsn = sh.[CoursSn5].Value
Case "SCHATZ"
curprixfut = sh.[CoursSchatz].Value
curprixsn = sh.[CoursSn2].Value
End Select
If (.Cells(i, 8) <> "" And .Cells(i, 8) <> 0) Or (.Cells(i, 7) <> "" And .Cells(i, 7) <> 0) Or (.Cells(i, 10) <> "" And .Cells(i, 10) <> 0) Or (.Cells(i, 9) <> "" And .Cells(i, 9) <> 0) Then
Errcours = 0
If .Cells(i, 7) > 0 And (.Cells(i, 8) < curprixfut - sh.[FourchetteFut] * 100 Or .Cells(i, 8) > curprixfut + sh.[FourchetteFut] * 100) Then Errcours = 1
If .Cells(i, 9) > 0 And (.Cells(i, 10) < curprixsn - sh.[FourchetteSn] * 100 Or .Cells(i, 10) > curprixsn + sh.[FourchetteSn] * 100) Then Errcours = 2
If Errcours > 0 Then
If wb.Sheets("Stock").ChercheLycos(.Cells(i, 1), 5, 2) = False Then
sh.Activate
.Cells(i, 8).Activate
strErr = "Valeur introuvable dans stock (" & .Cells(i, 1) & ")" & Chr(13) & Chr(13)
End If
If UpHisto Then
' HistoAccess.Et_mR1.Caption = "Cours incohérent"
' HistoAccess.Et_mR1.Visible = True
End If
If MsgBox(strErr & "Ce cours semble incohérent par rapport au prix de marché. Stopper la macro et corriger ?", vbYesNo) = vbYes Then GoTo fin
End If
End If
End If
Next i
End With
' If UpHisto Then HistoAccess.Et_mG1.Visible = True
'Paramètres de la connexion
If cnx.State = 0 Then Set cnx = Ini_cnx(cnx)
If rst.State = 0 Then Set rst = Ini_rst(rst)
If rstv.State = 0 Then Set rstv = Ini_rst(rstv)
'Paramètres du recordset
With rst
.Open "DELETE FROM POSE_OPERATIONS_JOUR", cnx, adOpenStatic, adLockOptimistic
.Open "SELECT * FROM POSE_OPERATIONS_JOUR", cnx, adOpenStatic, adLockOptimistic
End With
'Update Sorties pour stats
rstv.Open "DELETE * FROM POSE_SORTIES WHERE DATE = #" & Format(ThisWorkbook.Sheets("Informations").[workdate], "mm/dd/yy") & "#", cnx, adOpenStatic, adLockOptimistic
rstv.Open "SELECT * FROM POSE_SORTIES", cnx, adOpenStatic, adLockOptimistic
With wb.Sheets("SynthèseJour").[Ventes]
For i = 3 To 252
If .Cells(i, 1) <> "" Then
rstv.AddNew
rstv("DATE") = Format(Check_Data(.Cells(i, 9), "Date", "Ventes"), "dd/mm/yy 00:00")
rstv("ISIN") = Check_Data(.Cells(i, 1), "String", "Ventes")
rstv("QTE") = Check_Data(.Cells(i, 2), "Double", "Ventes")
rstv("PXREV") = Check_Data(.Cells(i, 3), "Double", "Ventes")
rstv("SPREV") = Check_Data(.Cells(i, 4), "Double", "Ventes")
rstv("PRIX") = Check_Data(.Cells(i, 5), "Double", "Ventes")
rstv("SPASW") = Check_Data(.Cells(i, 6), "Double", "Ventes")
rstv("SOCIETE") = Check_Data(.Cells(i, 7), "String", "Ventes")
rstv("CLIENT") = Check_Data(.Cells(i, 8), "String", "Ventes")
End If
Next i
End With
' If UpHisto Then HistoAccess.Et_mG2.Visible = True
'Mise à jour des positions vidées
With sh.[Op_vidage]
For i = 5 To 254
' With HistoAccess
' .StatusBar.Panels(1).Text = "Mise à jour des positions vidées - " & Round((i - 5) / 374 * 100, 0) & "%"
' .ProgressBar.Value = i - 5
' .Repaint
' End With
If .Cells(i, 1) <> "" Then Call addop(rst, sh.[Op_vidage], CInt(i), 0, "Update DB")
Next i
End With
'Mise à jour des opérations
With sh.[Op_liste]
i = 5
' HistoAccess.ProgressBar.max = wb.Sheets("Data").[histo_j].Cells(3, 1).End(xlDown).row - 10
For i = 5 To wb.Sheets("Data").[histo_j].Cells(3, 1).End(xlDown).row - 5
' With HistoAccess
' .StatusBar.Panels(1).Text = "Mise à jour des opérations - " & Round((i - 5) / (HistoAccess.ProgressBar.max) * 100, 0) & "%"
' .ProgressBar.Value = i - 5
' .Repaint
' End With
If .Cells(i, 1) <> "" And (.Cells(i, 4) <> 0 Or .Cells(i, 7) <> 0 Or .Cells(i, 9) <> 0) Then
Call addop(rst, sh.[Op_liste], CInt(i), 2, "Update DB")
rst.Update
End If
Next i
End With
'If UpHisto Then HistoAccess.Et_mG3.Visible = True
'Update et fermerture du recordset
With rst
If Not .RecordCount = 0 Then
.UpdateBatch
If .State <> 0 Then .Close
End If
End With
With rstv
If Not .RecordCount = 0 Then
.UpdateBatch
If .State <> 0 Then .Close
End If
End With
'Update Histo pour Konzult
If UpHisto Then
Save_Histo_tmp "Update DB"
' HistoAccess.Et_mG4.Visible = True
End If
'Update résultats
With wb.Sheets("SynthèseJour")
If rstv.State <> adStateClosed Then rstv.Close
rstv.Open "DELETE FROM POSE_RESULTATS WHERE [DATE] = #" & Format(CDate(wb.Sheets("Informations").[workdate].Value), "YYYY/mm/dd") & "#"
rstv.Open "POSE_RESULTATS"
For i = 8 To 257
If .Cells(i, 13) = "" Then Exit For
rstv.AddNew
rstv("DATE") = wb.Sheets("Informations").[workdate]
rstv("ISIN") = Check_Data(.Cells(i, 13), "String", "Pointage")
rstv("STOCK") = Check_Data(.Cells(i, 29), "Double", "Pointage")
rstv("ACHATS") = Check_Data(.Cells(i, 30), "Double", "Pointage")
rstv("VENTES") = Check_Data(.Cells(i, 31), "Double", "Pointage")
rstv("COUPONS") = Check_Data(.Cells(i, 32), "Double", "Pointage")
Next i
rstv.UpdateBatch
' HistoAccess.Et_mG5.Visible = True
End With
'Update coupons
With wb.Sheets("Pointage")
If .[CpnDetach] > 0 Then
If rstv.State <> adStateClosed Then rstv.Close
rstv.Open "DELETE FROM POSE_COUPONS WHERE [DATE] = #" & Format(CDate(wb.Sheets("Informations").[workdate].Value), "YYYY/mm/dd") & "#"
rstv.Open "POSE_COUPONS"
j = 0
For i = 8 To 257
If .Cells(i, 19) = True And .Cells(i, 19) <> "" Then
rstv.AddNew
rstv("DATE") = wb.Sheets("Informations").[workdate]
rstv("ISIN") = Check_Data(.Cells(i, 3), "String", "Pointage")
rstv("TITRES") = Check_Data(.Cells(i, 5), "Long", "Pointage")
rstv("MONTANT") = Check_Data(.Cells(i, 16), "Double", "Pointage")
rstv("TAUX") = Check_Data(wb.Sheets("Data").Cells(.Cells(i, 1) + 9, 31), "Double", "Pointage")
End If
Next i
rstv.UpdateBatch
End If
' HistoAccess.Et_mG6.Visible = True
End With
'Fin de la macro
Set rst = Flush_rst(rst, False, True)
Set rstv = Flush_rst(rstv, False, True)
If UpHisto Then Set cnx = Flush_cnx(cnx)
' With HistoAccess
' .StatusBar.Panels(1).Text = "Update terminé !"
' .Et_btnClose.Enabled = True
' .Repaint
' End With
update_opjour = True
Call check_histo
Check_Errors
' If UpHisto Then HistoAccess.Et_mG7.Visible = True
Exit Function
'Si erreur plus haut
fin:
' Unload HistoAccess
update_opjour = False
Check_Errors
End Function
Function addop(rst As Recordset, Rng As Range, line As Integer, x As Integer, source As String)
source = source & " > Enregistrement Op"
With Rng
rst.AddNew
rst("DATE") = ThisWorkbook.Sheets("Informations").[workdate]
rst("MAJ") = CDate(Now())
rst("ISIN") = Check_Data(.Cells(line, 1), "String", source)
If .Cells(line, 2) < 0 Then rst("SENS") = "V" Else: rst("SENS") = "A"
rst("QUANTITE") = Check_Data(.Cells(line, 2 + x), "Double", source)
rst("PRIX") = Check_Data(.Cells(line, 3 + x), "Double", source)
rst("ASW") = Check_Data(ThisWorkbook.Sheets("SynthèseJour").[Synth_area_SpdMoy].Cells(line - 4, 3), "Double", source)
If x = 0 Then rst("ASW") = Check_Data(.Cells(line, 12), "Double", source)
rst("TYPE_FUT") = Check_Data(.Cells(line, 4 + x), "String", source)
rst("QTE_FUT") = Check_Data(.Cells(line, 5 + x), "Double", source)
rst("PX_FUT") = Check_Data(.Cells(line, 6 + x), "Double", source)
rst("QTE_SN") = Check_Data(.Cells(line, 7 + x), "Double", source)
rst("PX_SN") = Check_Data(.Cells(line, 8 + x), "Double", source)
End With
End Function
Public Function check_newvals(Optional ByVal auto As Boolean = False) As Long
'Verifie l'existence ds posenego des valeurs non présentes dans le stock
'--AJOUT MS --------------------------------------------------
Dim strLecheance As String
Dim strLFutrure As String
Set wb = ThisWorkbook
Set sh = wb.Sheets("Opéjour")
Dim isin As String, type_fut As String, maturite As Date, quantite As Long, prix As Double
With sh.[Op_area_saisie]
i = 1
j = 0
While .Cells(i, 1).Value <> ""
'Si la valeur n'est pas encore suivie
If .Cells(i, 6).Value = 0 Then
quantite = .Cells(i, 2) - .Cells(i, 5)
If quantite <> 0 Then
isin = .Cells(i, 1).Value
prix = (.Cells(i, 2) * .Cells(i, 3) - .Cells(i, 4) * .Cells(i, 5)) / quantite
j = j + 1
'Requete des paramètres de la valeur : Maturité et Couverture
'--AJOUT MS --------------------------------------------------
If .Cells(i, 40).Value <> "" Then
strLecheance = .Cells(i, 40).Value
If IsDate(strLecheance) Then
strLecheance = .Cells(i, 40)
strLFutrure = Fonctions.FutureByMaturity(CDate(strLecheance))
Else
End If
End If
With RicInfos
If j = 1 Then
InOut.IniInsertions
.Autohide = "X"
Dim rtfields(0) As String
rtfields(0) = "RICS"
End If
.lIsin = isin
RtInst1.RtQuery .lIsin, rtfields, , "code"
'Ajout effectif dans la liste d'attente
'--AJOUT MS --------------------------------------------------
'InOut.add_new_val j, isin, CDate(.Lecheance), .Lfuture, quantite, prix
'If IsDate(strLecheance) Then
InOut.add_new_val j, isin, CDate(strLecheance), strLFutrure, quantite, prix
'Else
'InOut.add_new_val j, isin, CDate("28/06/2020"), strLFutrure, quantite, prix
'End If
End With
End If
End If
i = i + 1
Wend
check_newvals = j
'Affichage du formulaire d'insertion des nouvelles valeurs
'Si au moins 1 nvlle val, et si procédure automatique (pendant saisie)
If j > 0 And auto = True Then
InOut.MultiPage1.Value = 0
InOut.lSaisie.Visible = True
InOut.btnPasser.Caption = "PASSER"
InOut.Show
End If
End With
End Function
Public Sub RefreshVals()
'Ajoute les nouvelles valeurs qui ne sont pas encore dans HISTO
Set wb = ThisWorkbook
Dim RstRef As New ADODB.Recordset
'Si validation, insertion des valeurs selectionnées
'Remplissage d'un tableau temporaire pour l'insertion dans le classeur
'Et insertion directe dans un recordset pour la base de données
With InOut.gdInsertions
If cnx.State = 0 Then Set cnx = Ini_cnx(cnx)
If rst.State = 0 Then Set rst = Ini_rst(rst)
Set RstRef = Ini_rst(RstRef)
rst.Open "POSE_VALEURS"
RstRef.Open "VALEURS_REFERENTIEL", , , , adCmdTableDirect
RstRef.Index = "ISIN"
i = 1
j = 0
While i <= .Rows - 1
If .TextMatrix(i, 5) <> "-" Then
rst.AddNew
rst("ISIN") = .TextMatrix(i, 0)
rst("ECHEANCE") = .TextMatrix(i, 1)
rst("TYPE_FUT") = .TextMatrix(i, 2)
'rst("OPERATEUR") = GetOperator N'existe pas pour l'instant (inutile)
j = j + 1
End If
With RstRef
.Seek rst("ISIN"), adSeekLastEQ
If .EOF Then
.AddNew
RstRef("ISIN") = rst("ISIN")
End If
End With
i = i + 1
Wend
End With
If j > 0 Then rst.Update 'Update dernier enregistrement pour actualiser la mise a jour
rst.UpdateBatch
RstRef.UpdateBatch
Set rst = Flush_rst(rst, True, True) 'Update complet, fermerture, et liberation mémoire
Set RstRef = Flush_rst(RstRef, True, True)
Set cnx = Flush_cnx(cnx)
RefreshHisto
End Sub
Public Sub RefreshHisto()
'Actualisation des Querytables (feuille Data)
Set wb = ThisWorkbook
With wb.Sheets("Data")
With .QueryTables("histo_veille")
.Connection = .Connection
.CommandText = .CommandText
.Refresh BackgroundQuery:=False
End With
With .QueryTables("liste_valeurs")
.Connection = .Connection
.CommandText = .CommandText
.Refresh BackgroundQuery:=False
End With
End With
End Sub