Eigenschaft RowSource konnte nicht gesetzt werden... und dann Absturz

  • Excel

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von INOPIAE.

    Eigenschaft RowSource konnte nicht gesetzt werden... und dann Absturz

    Hallo zusammen,
    nachdem meine eigenen Recherchen und Versuche alle im Sande verlaufen sind, wenn ich mich nun ans Forum, in der Hoffnung hier Hinweise, neue Impulse oder gar eine Lösung zu erhalten.

    Folgendes Problem bereitet mir Schwierigkeiten:
    Ich habe ein Datenblatt, in dem untereinander insg. sechs definierte Tabellen eingefügt sind.
    Da mehrere Personen mit dem Blatt arbeiten, wurde es gegen unbeabsichtigte Veränderungen geschützt.
    Um bei aktivem Blattschutz dennoch Zeilen hinzufügen oder entfernen zu können, hab ich einen passende UserForm mit einer ListBox und zwei CommandButtons aufgebaut.
    Wird die UserForm geöffnet, wird der Inhalt der ausgewählten definierten Tabelle in die ListBox geladen. Nun kann man sich in der ListBox die Zeile anwählen welche gelöscht oder unter der eine neue Zeile eingefügt werden soll.

    Klappt alles wie geplant, aber… nur solange man ein Datenblatt auf hat.
    Öffnet man zwei solcher Datenblätter gleichzeitig erhalte ich bei der Aktion „Zeile einfügen über UserForm“ folgende Fehlermeldung woraufhin Excel im Nachgang komplett abstürzt:

    "Forms.Form1 – Programmabbruch.-2147024882 – Eigenschaft RowSource konnte nicht gesetzt werden. Für diesen Vorgang sind nicht genügend Speicherressourcen verfügbar."

    Merkwürdig ist auch, dass der Fehler nur bei einer der beiden offenen Datei auftritt. Die zweite lässt sich wie vorgesehen bearbeiten.

    Da alle Tabellen in den offenen Datenblätter die gleiche Namen haben (tab_1, tab_2, tab_3, etc) und diese Namen dann doppelt vorhanden sind (einmal je Datei), hatte ich hier das Problem vermutet. Eine Umbenennung brachte jedoch keinen Erfolg.
    Auch eine Umbenennung der UserForms in UF1 und UF2 hatte null positive Auswirkung.

    Als Fehler wird die Zeile 57
    - Me.ListBox1.RowSource = ThisWorkbook.ActiveSheet.ListObjects(strName)
    im Abschnitt 'Listbox aktualisieren in meinem Code angegeben.

    Hier die Gesamtübersicht:

    Spoiler anzeigen

    Visual Basic-Quellcode

    1. Private Sub CommandButton2_Click() 'erweitern
    2. On Error GoTo ENDE
    3. Dim wks As Object: Set wks = ThisWorkbook.ActiveSheet
    4. Dim strName As String
    5. 'Welche Tabelle ist aktiv?
    6. strName = ActiveCell.ListObject.Name
    7. Dim tbl As ListObject: Set tbl = wks.ListObjects(strName)
    8. 'Zeilen
    9. 'erste
    10. Dim EZ As Integer
    11. EZ = tbl.ListRows(1).Range.Row
    12. 'letzte
    13. Dim LZ As Integer
    14. Dim adrZ As String
    15. adrZ = Split(tbl.Range.Address, ":", -1, vbTextCompare)(1)
    16. LZ = wks.Range(adrZ).Row
    17. 'Spalten
    18. 'erste
    19. Dim ES As Integer
    20. ES = tbl.ListColumns(1).Range.Column
    21. 'letzte
    22. Dim LS As Integer
    23. Dim adrS As String
    24. adrS = Split(tbl.Range.Address, ":", -1, vbTextCompare)(1)
    25. LS = wks.Range(adrS).Column
    26. 'Blatt entsperren
    27. wks.Unprotect
    28. 'Tabelle anpassen
    29. If Me.ListBox1 + 1 > LZ Then
    30. 'Zeile einfügen
    31. Rows(Me.ListBox1 + 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
    32. 'Tabellengröße anpassen
    33. tbl.Resize Range(wks.Cells(EZ - 1, ES), wks.Cells(LZ + 1, LS))
    34. Else
    35. 'Zeile einfügen
    36. Rows(Me.ListBox1 + 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
    37. End If
    38. 'Listbox aktualisieren
    39. Me.ListBox1.RowSource = ThisWorkbook.ActiveSheet.ListObjects(strName)
    40. 'Me.ListBox1.RowSource = tbl.DataBodyRange.Address
    41. ENDE:
    42. 'Fehlermeldung anzeigen
    43. If Err.Number <> 0 Then
    44. MsgBox _
    45. Err.Number & _
    46. " - " & _
    47. Err.Description & Chr(13) & Chr(13) & _
    48. "Fehler Makro CommandButton2_Click.", , _
    49. Err.Source & " - Programmabbruch."
    50. End If
    51. 'Blatt sperren
    52. wks.Protect
    53. 'Aufräumen
    54. Set wks = Nothing
    55. Set tbl = Nothing
    56. Set oListZ = Nothing
    57. Set oListS = Nothing
    58. End Sub




    Hat jemand von Euch eine Ahnung, wie ich hier die Kuh vom Eis kriege?
    Sagt bescheid, wenn Ihr die Datei benötigt.

    Vielen Dank im Voraus für Eure Unterstützung.

    Bei evtl. Fragen stehe ich gerne zur Verfügung.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Marco123“ ()

    Versuche doch die Variable tbl As ListObject beim Laden des Formulars zu setzen und nicht erst beim Klicken auf einen Button.

    Und später machst Du dies:

    Visual Basic-Quellcode

    1. ​ Me.ListBox1.RowSource = tbl
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Hallo INOPIAE,

    INOPIAE schrieb:

    Versuche doch die Variable tbl As ListObject beim Laden des Formulars zu setzen und nicht erst beim Klicken auf einen Button.

    Und später machst Du dies:

    Visual Basic-Quellcode

    1. Me.ListBox1.RowSource = tbl


    Das geschieht bereits beim Event Userform_Initialize()

    Spoiler anzeigen

    Visual Basic-Quellcode

    1. Private Sub UserForm_Initialize()
    2. On Error GoTo ENDE
    3. Dim strName As String
    4. 'Welche Tabelle ist aktiv?
    5. strName = ActiveCell.ListObject.Name
    6. 'Userform einstellen
    7. With Me.ListBox1
    8. 'Überschriften
    9. .ColumnHeads = True
    10. 'Spaltenanzahl fetslegen
    11. .ColumnCount = 3
    12. 'Listbox leeren
    13. '.Clear
    14. 'Listbox Rowsource
    15. .RowSource = ThisWorkbook.ActiveSheet.ListObjects(strName)
    16. 'erste EIntrag anwählen
    17. '.Selected(0) = True
    18. End With
    19. ENDE:
    20. 'Fehlermeldung anzeigen
    21. If Err.Number <> 0 Then
    22. MsgBox _
    23. Err.Number & _
    24. " - " & _
    25. Err.Description & Chr(13) & Chr(13) & _
    26. "Fehler Userform_Initialize." , , _
    27. Err.Source & " - Programmabbruch."
    28. End If
    29. End Sub




    Das funktioniert auch alles.
    Mit dem .Rowsource-Befehl in CommandButton2_Click wird der nun geänderte Inhalt in die ListBox übertragen.
    Auch das funktioniert ... wenn nur eine Datei offen ist.

    Sind zwei gleiche Dateien offen, entsteht dann hier der Fehler.

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

    Liegt der Code innerhalb einer Datei oder innerhalb eines Addins?

    Was bedeutet "Sind zwei gleiche Dateien offen,"?

    Du machst das mit den Variablen so:

    Visual Basic-Quellcode

    1. ​Private tbl as Listobject
    2. Private Sub UserForm_Initialize()
    3. ...
    4. Dim strName As String
    5. strName = ActiveCell.ListObject.Name
    6. Set tbl = wks.ListObjects(strName)
    7. ...
    8. .RowSource = tbl
    9. ...
    10. End Sub
    11. Private Sub CommandButton2_Click()
    12. ...
    13. Me.ListBox1.RowSource = tbl
    14. ...
    15. End Sub
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Der Code liegt in der Datei.

    Bei der Datei handelt es sich um eine Vorlage für ein technische Datenblatt (TDB).
    Diese wird genommen um TDBs für Produkte zu erstellen.
    Die Datei wird also vervielfältigt.

    Solange man nur ein TDB bearbeitet, läuft alles wie am Schnürchen.
    Hat man nun aber zwei TDBs offen, kommt es zur o.g. Fehlermeldung bzw. zum anschließenden Absturz.

    Deine Vorschlag hab ich grade umgesetzt, der Ausgang ist jedoch der selbe :(

    Würde es helfen, wenn ich die Datei hochlade?
    Lagere den Code mal in ein Excel-AddIn aus.
    Falls Du noch kein Ribbon angelegt hast, lagere Deine Schaltflächen in einen eigenen Bereich im Ribbon aus.http://​[url]https://github.com/fernandreu/office-ribbonx-editor
    [/url]
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Guten Morgen,

    wenn ich Deinen Ansatz richtig verstehe, wäre das eine Maßnahme für eine Person, da die Funktion im Ribbon angelegt wird und falls mehrere Personen die Datei(en) benutzen, müsste alle diese Auslagerung vornehmen, richtig?

    Sollte dem so sein, würde ich gerne weiter nach einer anderen Lösung suchen.

    Danke jedoch für den Tipp. Der hilft mir tatsächlich in einem anderen Projekt weiter.
    Der Ansatz ist:
    Wenn Du keinen Code hast der ein Zellereignis abruft, sollte der ganze Code in einer Add.In-Datei liegen. Die Dateien mit den Daten sind dann Makro frei.
    Alle Personen, die die Daten-Dateien bearbeiten sollen, bekommen das AddIn installiert.

    Das AddIn kann auch Hilfstabellen einthalten. Diese sind dann aber für den Nutzer nicht sichtbar.

    Damit im AddIn die Funktionalitäten aufgerufen werden können, sollten diese über das Ribbon zur Verfügung gestellt werden.
    Natürlich muss im AddIn geprüft werden, ob die Logik zur aktuellen Datei passt. Dies kann relativ einfach über die Datei-Eigenschaften gelöst werden. (CustomDocumentProperties)

    Mehrere AddIns können sich auch ein Ribbon teilen.

    Vorteile dieses Ansatzes:
    Die Wartung des Codes ist einfacher. Es muss bei Bedarf nur die AddIn-Datei ausgewechselt werden. Codepflege in tausenden Dateien macht keinen Spaß.
    Gewisse Funktionalitäten können, dann nur von den Personen ausgeführt werden, die das AddIn eingebunden haben.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).