VBA Code Moduln aktualisieren

  • Excel

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von warbe.

    VBA Code Moduln aktualisieren

    Wenn ein VBA-Projekt an einen oder mehrere Nutzer übergeben wurde werden Änderungen mühsam. Da die Nutzer in ihre Arbeitsmappe Daten eingetragen haben, müssen Code Änderungen kopiert werden. Weil der VBA-Editor dafür nur sehr bedingt geeignete Mittel zur Verfügung stellt, bleibt nur: Modul für Modul aus der Entwickler-Arbeitsmappe exportieren, in der Nutzer-Arbeitsmappe löschen und neu importieren. Ich habe dafür ein VBA-Projekt in einer dedizierten Arbeitsmappe CoMMa.xlsm erstellt, die - im Normalfall selber unsichtbar - einen Nutzerdialog anzeigt, der Export, Import, Remove, Synchronisation, Transfer und Code-Cleanup für beliebig viele Moduln in geöffneten Arbeitsmappen unterstützt. Die Aktionen sind auch für VBA-Code in Daten Moduln (Arbeitsmappe und Arbeitsblätter) möglich. Da für diese Export, Remove Import nicht möglich ist, werden alle VBA-Code-Zeilen einzeln kopiert. Eine typische Aktion stellt sich wie folgt dar:

    1. Schritt: Operation und Quell- und Ziel-Arbeitsmappe auswählen


    2. Schritt: Code Moduln auswählen und Operation ausführen


    3. Schritt: Ergebnis Log ansehen


    Erwähnen möchte ich noch, dass ein neues/zusätzliches Arbeitsblatt komplett transferiert/synchronisiert werden kann, solange es in der Ziel-Arbeitsmappe noch nicht existiert - ohne dass dabei Rückwärtslinks zum Quell-Arbeitsblatt enstehen!
    Wer sich mit dieser Materie schon mal auseinander gesetzt hat und an meiner Problemlösung interessiert ist, ist herzlich eingeladen die Arbeitsmappe zu verwenden und mit Feedback nicht zu sparen. Der Quellcode in der Arbeitsmappe ist leider zu umfangreich um ihn hier direkt zu publizieren. Für diejenigen, die sich an solch einer Löung selbst versuchen wollen oder sogar ein VBA-Projekt erstellen möchten, welches sich selbst aktualisiert, hier die beiden entralen Prozeduren:

    Quellcode

    1. Public Function CoMReplaceLbL(ByVal wbkTarget As Workbook, _
    2. Optional ByVal sExportFile As String = vbNullString, _
    3. Optional ByVal wbkSource As Workbook = Nothing, _
    4. Optional ByRef sCoModName As String = vbNullString, _
    5. Optional ByRef lUpdated As Long = 0, _
    6. Optional ByRef lAdded As Long = 0, _
    7. Optional ByRef lDeleted As Long = 0, _
    8. Optional ByRef lSource As Long = 0, _
    9. Optional ByRef lTarget As Long = 0, _
    10. Optional ByRef sResult As String = vbNullString) As String
    11. ' -----------------------------------------------------------------------------
    12. ' Replaces the Code Module in 'wbkTarget' by one with the same name either
    13. ' provided through an 'sExportFile' (.bas or .cls) or through 'wbkSource' and
    14. ' 'sCoModName'. When an 'sExportFile' is provided, 'wbkSource' and 'sCoModName'
    15. ' are ignored and the 'sCoModName' is determined by the export files name.
    16. ' The function is able to replace its own Code Modules (except to Code Module
    17. ' this function resides) provided the source is an 'sExportFile'.
    18. ' The function returns a vbNullString or a short error message.
    19. ' lUpdated, lAdded, lDeleted, lSource, lTarget, sResult are optional return
    20. ' values.
    21. ' See also: http://www.excelforum.com/excel-programming-vba-macros/1116013-when-programmaticaly-remove-replace-code-modules-doesnt-work.html
    22. '
    23. ' Autohor: W. Rauschenberger, Berlin Dec 2015
    24. ' -------------------------------------------------------------------------------------
    25. ' ------------- Should be adjusted when applicable !!!!! ----------
    26. Const sMyOwnCoM As String = "clsCoMMa" ' The Code Module in which this function resides
    27. Const sDebugName As String = "CoMReplaceLbL" ' My own name (to be replaced when changed)
    28. ' -----------------------------------------------------------------
    29. Const sVBAttribute As String = "Attribute VB_"
    30. Const sVbName As String = "Attribute VB_Name = "
    31. Const sTempSuffix As String = "_temp_" ' Temorary Source Code Module's name suffix
    32. Const sComment As String = "'"
    33. Const sBackSlash As String = "\"
    34. Const sDot As String = "."
    35. Const sPhcom As String = "<com>" ' Placeholder for error messages below
    36. Const sPhwbk As String = "<wbk>" ' Placeholder for error messages below
    37. Const sPhfile As String = "<file>" ' Placeholder for error messages below
    38. Const sMsgCoMExcl As String = "When the target Workbook is 'ThisWorkbook', '<com>' cannot be replaced!"
    39. Const sMsgFileError As String = "The provided file '<file>' does not exist!"
    40. Const sMsgNoCoM As String = "No Code Module's name is provided!"
    41. Const sMsgNoExport As String = "'<file>' is not an exported Code Module!"
    42. Const sMsgNoSource As String = "Neither an 'sExportFile' nor a 'wbkSource' provided!"
    43. Const sMsgNoSrcCoM As String = "The Code Module '<com>' not exists in source Workbook '<wbk>'!"
    44. Const sMsgNoTarget As String = "No Target Workbook provided!"
    45. Const sMsgNoTrgtCoM As String = "Code Module '<com>'not exists in target Workbook '<wbk>'!"
    46. Const sMsgSrcIsTrgt As String = "Source and Target Workbbok cannot be the same!"
    47. Const sMsgUsrFrm As String = "Code Module '<com>' must not be UserForm!"
    48. Const sLogNoChange As String = "(nothig changed, source and target were already equal)"
    49. Const sLogAdded As String = "(<a> lines added)"
    50. Const sSkp As String = " unchanged" ' Log line yet not implemented
    51. Const sRep As String = " replaced" ' Log line yet not implemented
    52. Const sAdd As String = " added" ' Log line yet not implemented
    53. Const sDel As String = " deleted" ' Log line yet not implemented
    54. Dim asFile() As String
    55. Dim asLines() As String
    56. Dim bRenamed As Boolean
    57. Dim bReplaceDirect As Boolean ' TRUE when no 'sExportFile' is provided
    58. Dim i As Long
    59. Dim lToBeReplaced As Long
    60. Dim lCoMType As enCompType
    61. Dim lUnchngd As Long
    62. Dim sComma As String
    63. Dim sErr As String ' Return error message
    64. Dim sLineNew As String
    65. Dim sLineOld As String
    66. Dim sTempFile As String
    67. Dim sTempCoMod As String
    68. Dim tsFile As TextStream
    69. Dim vbcSource As VBComponent
    70. Dim vbcTarget As VBComponent
    71. Dim vbcmSource As VBIDE.CodeModule
    72. Dim vbcmTarget As VBIDE.CodeModule
    73. On Error GoTo on_error
    74. CoMReplaceLbL = vbNullString
    75. If Len(sExportFile) <> 0 Then
    76. '~~> Terminate when 'sExportFile' doesn't exist
    77. With New FileSystemObject
    78. If Not .FileExists(sExportFile) Then
    79. CoMReplaceLbL = Replace(sMsgFileError, sPhfile, sExportFile)
    80. Exit Function
    81. End If
    82. End With
    83. '~~> Extract the Code Module's name from the provided 'sExportFile'
    84. asFile = Split(sExportFile, sBackSlash)
    85. sCoModName = asFile(UBound(asFile))
    86. asFile = Split(sCoModName, sDot)
    87. sCoModName = asFile(LBound(asFile))
    88. '~~>Terminate if no Target Workboook provided
    89. If wbkTarget Is Nothing Then
    90. CoMReplaceLbL = sMsgNoTarget
    91. Exit Function
    92. End If
    93. '~~> Terminate when target is ThisWorkbbok and 'sCoModName is the excluded CoM
    94. If wbkTarget.Name = ThisWorkbook.Name _
    95. And sCoModName = sMyOwnCoM Then
    96. CoMReplaceLbL = Replace(sMsgCoMExcl, sPhcom, sCoModName)
    97. Exit Function
    98. End If
    99. '~~>Terminate when the 'sCoModName' derived from 'sExportFile' does not exist in 'wbkTarget'
    100. Set vbcTarget = Nothing
    101. On Error Resume Next
    102. Set vbcTarget = wbkTarget.VBProject.VBComponents(sCoModName)
    103. If vbcTarget Is Nothing Then
    104. sErr = Replace(sMsgNoTrgtCoM, sPhcom, sCoModName)
    105. CoMReplaceLbL = Replace(sErr, sPhwbk, wbkTarget.Name)
    106. Exit Function
    107. End If
    108. Else
    109. '~~> Terminate when neither a 'sExportFile' nor a 'wbkSource' is provided
    110. If wbkSource Is Nothing Then
    111. CoMReplaceLbL = sMsgNoSource
    112. Exit Function
    113. End If
    114. '~~> Terminate when 'wbkTarget' is identical with 'wbkSource'
    115. If wbkSource.Name = wbkTarget.Name Then
    116. CoMReplaceLbL = sMsgSrcIsTrgt
    117. Exit Function
    118. End If
    119. '~~> Terminate when no 'sCoModName' is provided
    120. If Len(sCoModName) = 0 Then
    121. CoMReplaceLbL = sMsgNoCoM
    122. Exit Function
    123. End If
    124. '~~> Terminate when target is ThisWorkbbok and 'sCoModName' is the excluded CoM
    125. If wbkTarget.Name = ThisWorkbook.Name _
    126. And sCoModName = sMyOwnCoM Then
    127. CoMReplaceLbL = Replace(sMsgCoMExcl, sPhcom, sCoModName)
    128. Exit Function
    129. End If
    130. ' -------------------------------------------------------------------------------
    131. ' When no 'sExportFile' is provided the code lines from 'wbkSource'.'sCoModName'
    132. ' are directly used for replacing the lines in the target Workbook's Code Module.
    133. ' -------------------------------------------------------------------------------
    134. '~~> Terminate when the 'sCoModName' does not exist in 'wbkSource'
    135. Set vbcSource = Nothing
    136. On Error Resume Next
    137. Set vbcSource = wbkSource.VBProject.VBComponents(sCoModName)
    138. If vbcSource Is Nothing Then
    139. sErr = Replace(sMsgNoSrcCoM, sPhcom, sCoModName)
    140. CoMReplaceLbL = Replace(sErr, sPhwbk, wbkSource.Name)
    141. Exit Function
    142. End If
    143. Set vbcmSource = vbcSource.CodeModule
    144. bReplaceDirect = True
    145. End If
    146. '~~> Terminate when the 'sCoModName' derived from 'sExportFile' does not exist in the 'wbkTarget'
    147. Set vbcTarget = Nothing
    148. On Error Resume Next
    149. Set vbcTarget = wbkTarget.VBProject.VBComponents(sCoModName)
    150. If vbcTarget Is Nothing Then
    151. sErr = Replace(sMsgNoTrgtCoM, sPhcom, sCoModName)
    152. CoMReplaceLbL = Replace(sErr, sPhwbk, wbkTarget.Name)
    153. Exit Function
    154. End If
    155. '~~> Terminate when 'sCoModName' is a UserForm
    156. If vbcTarget.Type = vbext_ct_MSForm Then
    157. CoMReplaceLbL = Replace(sMsgUsrFrm, sPhcom, sCoModName)
    158. Exit Function
    159. End If
    160. Set vbcmTarget = vbcTarget.CodeModule
    161. If Not bReplaceDirect Then
    162. ' ----------------------------------------------------------------------------
    163. ' When the new code is provided through an export file, the content cannot be
    164. ' used directly to line-wise replace the target Code Module. The content is
    165. ' copied into a temporary file by replacing the name in 'Attribute VB_Name = '
    166. ' by a temporary Code Module name and 'out-commenting' all code lines. This
    167. ' modified export file is imported under the temporary Code Module name, now
    168. ' not causing any code conflicts. When this code lines are used to replace
    169. ' those of the target Code Module, the comment sign is removed before.
    170. ' ----------------------------------------------------------------------------
    171. With New FileSystemObject
    172. '~~> Get the content of the sExportFile into the array asLines
    173. Set tsFile = .OpenTextFile(sExportFile, ForReading)
    174. If tsFile.AtEndOfStream Then Erase asLines Else asLines = Split(tsFile.ReadAll, vbLf)
    175. Set tsFile = Nothing
    176. End With
    177. sTempCoMod = sCoModName & sTempSuffix
    178. sTempFile = Replace(sExportFile, sCoModName, sTempCoMod)
    179. bRenamed = False
    180. With New FileSystemObject
    181. If .FileExists(sTempFile) Then .DeleteFile sTempFile
    182. With .CreateTextFile(sTempFile)
    183. For i = LBound(asLines) To UBound(asLines) - 1 ' Drop last (always empty) line to prevent duplication
    184. sLineNew = asLines(i)
    185. If Len(sLineNew) > 1 Then sLineNew = Left(sLineNew, Len(sLineNew) - 1) Else sLineNew = vbNullString
    186. If Not bRenamed Then
    187. ' ------------------------------------------------------------------
    188. ' All lines before the VBName had been replaced and all lines after
    189. ' when starting with 'Attribute VB_' are transferred unchanched.
    190. ' ------------------------------------------------------------------
    191. If Mid$(sLineNew, 1, Len(sVbName)) = sVbName Then
    192. '~~> Modify name in VBAttribute line
    193. sLineNew = Replace(asLines(i), sCoModName, sTempCoMod)
    194. sLineNew = Left(sLineNew, Len(sLineNew) - 1)
    195. .WriteLine sLineNew
    196. bRenamed = True
    197. End If
    198. If Not bRenamed Then .WriteLine sLineNew ' write lines before the vbname line as is!
    199. ElseIf Mid$(sLineNew, 1, Len(sVBAttribute)) = sVBAttribute Then
    200. '~~> Write VBAttribute line unmodified
    201. .WriteLine sLineNew
    202. Else
    203. '~~> Modify line to become a comment line
    204. .WriteLine sComment & sLineNew
    205. End If
    206. Next i
    207. .Close
    208. End With
    209. If Not bRenamed Then
    210. ' -------------------------------------------------------------------------------------
    211. ' When no 'Attribute VB_Name' line was found to rename the Code Module, the export file
    212. ' is not regarded as one. The temp file is deleted and the function is terminated.
    213. ' -------------------------------------------------------------------------------------
    214. .DeleteFile sTempFile
    215. CoMReplaceLbL = Replace(sMsgNoExport, sPhfile, sExportFile)
    216. Exit Function
    217. End If
    218. End With
    219. '~~> Import the modified export file under the temporary Code Module name
    220. wbkTarget.VBProject.VBComponents.Import sTempFile
    221. Set vbcmSource = wbkTarget.VBProject.VBComponents(sTempCoMod).CodeModule
    222. ' Set vbcmSource = vbcSource.CodeModule
    223. bReplaceDirect = False
    224. End If
    225. ' -------------------------------------------------------------
    226. ' With the lines of this 'image' of the new Code Modules's code
    227. ' update the existing Code Module by un-commenting each line.
    228. ' -------------------------------------------------------------
    229. lAdded = 0
    230. lUpdated = 0
    231. lDeleted = 0
    232. lUnchngd = 0
    233. lTarget = vbcmTarget.CountOfLines
    234. lSource = vbcmSource.CountOfLines
    235. If lSource < lTarget Then lToBeReplaced = lSource Else lToBeReplaced = lTarget
    236. With vbcmTarget
    237. '~~> Replace all 'old' lines with the 'new' lines
    238. For i = 1 To lToBeReplaced
    239. sLineNew = vbcmSource.Lines(i, 1)
    240. sLineOld = vbcmTarget.Lines(i, 1)
    241. If Not bReplaceDirect Then
    242. '~~> Un-Comment line
    243. If Len(sLineNew) <= 1 Then sLineNew = "" Else sLineNew = Mid(sLineNew, 2)
    244. End If
    245. If Trim(sLineNew) <> Trim(sLineOld) Then
    246. .ReplaceLine i, sLineNew
    247. lUpdated = lUpdated + 1
    248. Else
    249. lUnchngd = lUnchngd + 1
    250. End If
    251. Next i
    252. '~~> Add new lines which exceed the number of 'old' lines
    253. While .CountOfLines < lSource
    254. sLineNew = vbcmSource.Lines(.CountOfLines + 1, 1)
    255. If Not bReplaceDirect Then
    256. '~~> Un-Comment line
    257. If Len(sLineNew) <= 1 Then sLineNew = " " Else sLineNew = Mid(sLineNew, 2)
    258. End If
    259. .InsertLines .CountOfLines + 1, sLineNew
    260. lAdded = lAdded + 1
    261. Wend
    262. '~~> Delete excessive lines
    263. If .CountOfLines > lSource Then
    264. lDeleted = .CountOfLines - lSource
    265. .DeleteLines lSource + 1, lDeleted
    266. End If
    267. End With
    268. sResult = vbNullString
    269. sComma = vbNullString
    270. If lUpdated = 0 And lAdded = 0 And lDeleted = 0 Then
    271. If lTarget <> 0 Then
    272. sResult = sResult & "no lines changed"
    273. sComma = ", "
    274. End If
    275. End If
    276. If lUpdated <> 0 Then
    277. sResult = sResult & lUpdated & " of " & lTarget & " target lines updated"
    278. sComma = ", "
    279. End If
    280. If lAdded <> 0 Then
    281. sResult = sResult & sComma & lAdded & " of " & lSource & " source lines added to target"
    282. sComma = ", "
    283. ElseIf lDeleted <> 0 Then
    284. sResult = sResult & sComma & lDeleted & " lines deleted from target"
    285. End If
    286. If Not bReplaceDirect Then
    287. ' -------------------------------------------------------------------------------------------
    288. ' When replacing the target code lines had not been done directly with the source code lines,
    289. ' the temporary imported Code Module and the temporary file are removed.
    290. ' -------------------------------------------------------------------------------------------
    291. wbkTarget.VBProject.VBComponents.Remove wbkTarget.VBProject.VBComponents(sTempCoMod)
    292. With New FileSystemObject
    293. If .FileExists(sTempFile) Then .DeleteFile sTempFile
    294. End With
    295. End If
    296. Exit Function
    297. on_error:
    298. Debug.Print "Error in '" & sMyOwnCoM & sDot & sDebugName & "'!"
    299. wbkTarget.VBProject.VBComponents.Remove wbkTarget.VBProject.VBComponents(sTempCoMod)
    300. With New FileSystemObject
    301. If .FileExists(sTempFile) Then .DeleteFile sTempFile
    302. End With
    303. End Function
    304. Public Function WshAddToWrkbk(ByVal wbkSource As Workbook, _
    305. ByVal wbkTarget As Workbook, _
    306. ByVal sCodeName As String) As Boolean
    307. ' -----------------------------------------------------------------
    308. ' Copies the sheet named 'sCodeName' from the 'wbkSource' to the
    309. ' 'wbkTarget' Workbook. Prevents back-links to the source Workbook
    310. ' by moving the sheet from a temporary copy. Removes all code lines
    311. ' in the temporary Worksheet before close to prevent compile errors
    312. ' because of the moved sheet. Returns FALSE when a sheet named
    313. ' 'sCodeName' already exists in 'wbkTarget'.
    314. ' -----------------------------------------------------------------
    315. Const sNameRefErr1 As String = "='#" ' Indicator for a name error
    316. Const sNameRefErr2 As String = "=#" ' Indicator for a name error
    317. Const sWbkNmTmpSffx As String = "_temp_"
    318. Const sDot As String = "."
    319. Dim bEvents As Boolean
    320. Dim nm As Name
    321. Dim nmSrc As Name
    322. Dim sWbkExt As String
    323. Dim sWbkNm As String
    324. Dim sWbkNmTmp As String
    325. Dim sWbkNmTmpFull As String
    326. Dim vbc As VBComponent
    327. Dim wbkTemp As Workbook
    328. Dim wsh As Worksheet
    329. Dim cllNames As Collection
    330. Dim sWshName As String
    331. Dim sWshBaseCname As String
    332. Dim wshTemp As Worksheet
    333. Dim bWshProtected As Boolean
    334. On Error GoTo on_error
    335. WshAddToWrkbk = False
    336. For Each wsh In wbkTarget.Sheets
    337. '~~> Exit with False when the sheet already exists in the target Workbook
    338. If wsh.CodeName = sCodeName Then Exit Function
    339. Next wsh
    340. '~~> Remove any name errors
    341. For Each nm In Application.Names
    342. If Left(nm.Value, Len(sNameRefErr1)) = sNameRefErr1 Or _
    343. Left(nm.Value, Len(sNameRefErr2)) = sNameRefErr2 Then
    344. nm.Delete
    345. End If
    346. Next nm
    347. '~~> Create a temporary source Workbook copy
    348. With wbkSource
    349. sWbkNm = Left(.Name, (InStrRev(.Name, sDot, -1, vbTextCompare) - 1))
    350. sWbkExt = Right(.Name, Len(.Name) - (InStrRev(.Name, sDot, -1, vbTextCompare) - 1))
    351. sWbkNmTmp = sWbkNm & sWbkNmTmpSffx & sWbkExt
    352. sWbkNmTmpFull = Replace(.FullName, .Name, sWbkNmTmp)
    353. With New FileSystemObject
    354. If .FileExists(sWbkNmTmpFull) Then .DeleteFile sWbkNmTmpFull
    355. End With
    356. .SaveCopyAs sWbkNmTmpFull
    357. End With
    358. Application.DisplayAlerts = False
    359. bEvents = Application.EnableEvents
    360. Application.EnableEvents = False
    361. Set wbkTemp = Workbooks.Open(sWbkNmTmpFull)
    362. With wbkTemp
    363. '~~> Add a spare sheet when the to be moved one is the only sheet in the source Workbook
    364. If .Sheets.Count = 1 Then .Sheets.Add
    365. '~~> Move the sheet to the target Workbook
    366. For Each wsh In .Sheets
    367. If wsh.CodeName = sCodeName Then
    368. wsh.Move After:=wbkTarget.Sheets(wbkTarget.Sheets.Count)
    369. Exit For
    370. End If
    371. Next wsh
    372. '~~> Remove all code lines in the temporary Workbook and close it
    373. For Each vbc In .VBProject.VBComponents
    374. With vbc.CodeModule
    375. If .CountOfLines > 0 Then .DeleteLines .CountOfLines
    376. End With
    377. Next vbc
    378. .Close SaveChanges:=False
    379. End With
    380. Application.EnableEvents = bEvents
    381. '~~> Remove the temprary Workbook
    382. With New FileSystemObject
    383. .DeleteFile sWbkNmTmpFull
    384. End With
    385. WshAddToWrkbk = True
    386. Exit Function
    387. on_error:
    388. Debug.Print "Error in 'clsCoMMa.WshAddToWrkbk'! (" & sCodeName & ")"
    389. End Function

    Bilder
    • CoMMa.png

      14,41 kB, 501×256, 1.543 mal angesehen
    • CoMMa-code-module-selection.png

      19,67 kB, 779×264, 1.433 mal angesehen
    • CoMMa_Log.png

      22,36 kB, 717×203, 1.408 mal angesehen
    Da es sich um eine fertige Lösung handelt, stimmt das wohl. Für eine "Umsortierung" bzw. entsprechender Hilfe dazu wäre ich dankbar. Zukünftiges dieser Art gerne gleich richtig. Leider kann ich nicht (bzw. nur mit etwas Aufwand) kontrollieren, ob der Link zur Arbeitsmappe in meiner Dropbox einen Download zulässt. Den Ort finde ich optimal, da er mir auf einfache Weise die Code-Aktualisierung ermöglicht.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „warbe“ ()

    Ich bevorzuge dafür lieber eine zentrale VBA-Bibliothek.
    Das hilft zwar nicht den Code in den Worksheets zu verwalten.
    Wenn du aber dort nur Instanzierungen und Aufrufe von Bibliotheks-Objekten und -Methoden drin hast und die Intelligenz dorthin verlagerst, kannst du die zentralen Klassen und Module austauschen und dir die ganzen Klimmzüge sparen.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Hallo!

    In einem Firmennetzwerk halte ich soetwas für gefährlich. Denn um den VBA-Code codegesteuert austauschen zu können muss man (über das Sicherheitscenter) den Zugriff auf das VBA-Projekt-Objektmodell vertrauen, was aber den Viren und Trojanern eine Tür öffnet.

    Gruß, René

    mumpel schrieb:

    In einem Firmennetzwerk halte ich soetwas für gefährlich

    Kann ich nur unterschreiben.

    Aber in den meisten großen Unternehmen ist das beschriebene Verfahren eh nur graue Theorie, weil der codegesteuerte Zugriff auf das VBA-Projekt per Group Policy verhindert wird.
    Da ist der Punkt "Zugriff auf das VBA-Projektobjektmodell vertrauen" ausgegraut und kann nicht verändert werden.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Die Datensicherheit ist auch in Gefahr. Wenn gerade jemand an der Datei arbeitet und ein anderer funkt mit einem VBA-Code dazwischen kann das schon mal zu unerwünschten Ergebnissen führen.

    mumpel schrieb:

    Wenn gerade jemand an der Datei arbeitet
    sind keine Modifikationen von außen möglich.

    Das gilt sowohl für direkte Code-Modifikation als auch für den Austausch eine VBA-Library.

    Aber einen zentralen Update führt man eh nicht im Tagesbetrieb durch.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Die Lösung ist vor allem dazu gedacht, eine VBA-Applikation auch dann noch ändern, korrigieren bzw. erweitern zu können, wenn der Kunde (i.d.R. nicht "in meiner Firma") bereits damit arbeitet, d.h. die Arbeitsmappe bereits Daten enthält. Die Idee dahinter entstammt meiner Präferenz für eine betmögliche Trennung von Entwicklung, Test, und Produktion. Im Sinne der erstellten Lösung handelt es sich bei einem Code-Transfer in eine "produktive" Arbeitsmappe also um einen "Rollout" einer neuen Version. Die Sicherheitsbedenken sind selbstverständlich relevant und können nur dadurch adressiert werden, dass die entsprechenden Sicherheitseinstelliungen nur temporär (z.B. zum Zweck des "rollout") geändert werden. Sollten die Sicherheitseinstellungen auch in einer reinen Entwicklungs- bzw. Testumgebung nicht veränderbar sein, ist das für meine Lösung ein ko-Kriterium.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „warbe“ ()

    ​Die Lösung ist vor allem dazu gedacht, eine VBA-Applikation auch dann noch ändern, korrigieren bzw. erweitern zu können, wenn der Nutzer bereits damit arbeitet, d.h. die Arbeitsmappe bereits Daten enthält.
    Wie gesagt, das wäre alles mit einer zentralen Lib auch gegeben und wesentlich eleganter.
    Und ohne die Einschränkungen, mit denen du jetzt lebst.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Die Kunden meiner VBA-Applikationen und ich befinden sich nicht in einer Firma. Solange der Kunde die Arbeitsmappe in der Cloud (z.B. Dropbox) nutzt, kann ich daran im Wartungsfall etwas ändern. Eine zentrale Code Lib ebenfalls in der Cloud? Ginge das überhaupt? Und wäre dann da tatsächlich der wesentliche Teil des VBA-Codes einer Arbeitmappe darin, einschließlich UserForms z.B. die ja meist von einerÄnderung betroffen ist? Ich lerne gerne was dazu und andere sollen auch davon profitieren. In diesem Sinne danke ich für jeden konstruktiven Beitrag.
    Mit der Cloud sehe ich keine Probleme, aber bei statischen Userforms wird's wohl nichts werden.
    Der Code-Behind lässt sich natürlich in eine Lib auslagern, aber das Layout?
    Das würde nur bei generischen Forms funktionieren, die man vor dem ersten Show dynamisch zusammenbaut.

    Aber ich sehe auch nicht, wie du mit deiner Methode das Layout der Forms modifizieren kannst.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Meine Lösung/Methode kopiert/transferiert die UserForm - samt Layout! - *) von der Test-Version in die Produktions-Version genauso wie alles Andere (Standard Moduln, Kassen Moduln, Arbeitsmappen-Code und Arbeitsblatt-Code) - und bei einem, in Zuge einer Änderung zusätzlich hinzugekommenen Arbeitsblatt, auch dieses samt und sonders. Die angewandten Transfer-Methoden unterscheiden sich natürlich etwas.
    *) Weil eine Änderung des Layouts nicht durch Vergleich der Layout-Dateien möglich ist, weil sich selbst unveränderte Layout-Dateien aus Test- und Produktions-Version exportiert, unterscheiden, wird das Layout einer UserForm beim Synchronize immer als geändert angesehen und mit transferiert.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „warbe“ ()