eigenes Kontextmenü für Spalte "A" ?

  • Excel

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von mumpel.

    eigenes Kontextmenü für Spalte "A" ?

    Hallo Forum,

    meine Frage ist, ist es möglich, nur für die Zellen in Spalte "A" ein eigenes Kontextmenü zu erstellen?

    Wenn ja, könnte mir dann bitte jemand auf die Sprünge helfen?

    Code zum vorzeigen, habe ich leider noch nicht, da ich nicht weiss, wie ich an diese Sache herangehen soll

    Danke

    Tom

    TomWi schrieb:

    nur für die Zellen in Spalte "A" ein eigenes Kontextmenü zu erstellen
    Nicht mit Bordmitteln.
    Da müsstest du schon ein eigenes Excel-AddIn schreiben.

    Was du machen kannst, ist Eingabe-Syntaxprüfung.

    Kannst du mal näher erläutern, wofür du das benötigst?
    Möglicherweise gibt's ja eine elegante Möglichkeit, das anders zu lösen.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Ok. Momemtan ist es so, dass ich 3 spalten habe. 1= Artikel, 2= Listenpreis, 3= Verkaufspreis.

    Verkaufspreis wird berechnet mit der formel Listenpreis/100* x

    Je nachdem welchen Zustand der Artikel hat, NEU oder GEBRAUCHT und was es für ein Artikel ist, ist "x" ein anderer Wert. Da ich nicht jedesmal x händisch eingeben möchte, dachte ich mir, ein Kontextmenü mit vorgegebenen Werten oder evtl. auch einer Textbox (wenn möglich), wäre ganz gut. Also wenn ich zum Beispiel Rechstklick auf den Artikel mache, will ich auswählen, welchen Wert "x" haben soll

    Danke
    Dann mach doch 4 Spalten (Artikel, Listenpreis, Faktor, Verkaufspreis) und die Faktor-Spalte bindest du an eine Liste (Daten..Datenüberprüfung..Liste).
    Falls du diese Funktionalität nicht kennst:
    http://www.tabellenexperte.de/eingabemoeglichkeiten-einschraenken/

    Die Variante ist wesentlich besser als ein Contextmenü, weil du sowohl die Möglichkeiten einer Direkteingabe als auch ein Dropdownmenü hast.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

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

    vielen Dank für den Link.
    Das klingt schon mal ganz ordenlich, was dort gezeigt wird.
    Leider bin ich dann aber an diese Liste(die ich vorher erstellen muss), gebunden, und kann nicht einfach einen Wert, der nicht in der Liste steht, eingeben, ohne die Datenprüfung für diese eine Zelle zu deaktivieren.

    Gibt es noch andere Möglichkeiten?
    Du hast was von einem ExcelAddin gesagt.
    Kannst Du mir da bitte ein paar Stichpunkte nennen, nach denen ich dann mal suchen könnte?
    Also speziell zum Thema Kontextmenü in Excel und nicht zum Thema ExcelAddIn.

    Vielen Dank für die Hilfe.

    Tom

    TomWi schrieb:

    Leider bin ich dann aber an diese Liste(die ich vorher erstellen muss), gebunden
    Wer behauptet das?
    Du musst ja nicht unbedingt anklicken, dass er eine Fehlermeldung ausgeben soll.
    Oder nur eine Informations-Fehlermeldung ausgeben.

    Wenn du Excel 2010 oder neuer verwendest, kannst du zwar immer noch kein eigenes Contextmenü erstellen, aber zumindest das bestehende Context-Menü erweitern.
    Aber das ist alles aufwändiger und anfälliger als die Excel-Standardfunktionen zu nutzen.
    msdn.microsoft.com/en-us/libra…g469862(v=office.14).aspx

    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

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

    Hallo!

    Meines Wissens kann man durchaus ein eigenes Kontextmenü erstellen. Hierbei deaktiviert man die Standardelemente (z.B. über eine Schleife) und fügt eigene Elemente ein.

    Über das Rechtsklick-Ereignis (Worksheet_BeforeRightClick) prüft man auf die Spalte. Ist es Spalte A (If Target.Column = 1) dann das Kontextmenü anpassen. Ist es eine andere Spalte setzt man das Kontextmenü einfach zurück (Application.CommandBars("Cell").Reset)

    Beispiel: vb-fun.de/cgi-bin/loadframe.pl?ID=vb/tipps/tip0062.shtml

    Gruß, René
    Habe das Beispiel gerade herunter geladen.
    Es funktioniert recht gut.
    Prinzipiell ist das ja der oben verlinkte Microsoft-Ansatz.

    Für die Eingrenzung des Context-Menüs auf Einzelzellen in der ersten Spalte bietet sich folgender Code für das Worksheet_BeforeRightClick-Event an:

    Visual Basic-Quellcode

    1. Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    2. If Target.Count = 1 And Not Intersect(Selection, Columns(1)) Is Nothing Then
    3. For Each cBar In Application.CommandBars
    4. If cBar.Name = cBarKontextName Then
    5. Application.CommandBars(cBarKontextName).ShowPopup
    6. Cancel = True
    7. Exit Sub
    8. End If
    9. Next
    10. End If
    11. End Sub

    Ein Reset ist gar nicht notwendig, da bereits durch das Cancel = True das Context-Menü auf das User-Menü beschränkt wird.

    Eine schöne Spielerei, aber für das Problem des TE würde ich vermutlich trotzdem den Ansatz über die Datenüberprüfung realisieren.

    Nichtsdestotrotz werde ich gelegentlich mal versuchen ein Contextmenu mit SubItems als Parameter zu erstellen, so wie es der TE eigentlich benötigen würde.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Ich habe jetzt eine Variante, die ein temporäres Contextmenü erstellt und deswegen keine Leichen nach Schließen der Anwendung hinterlässt.
    Im Codebereich der Arbeitsmappe (DieseArbeitsmappe bzw. ThisWorkbook):

    Visual Basic-Quellcode

    1. ​Private Sub Workbook_Open()
    2. CreateCommandBar "DefaultValues", "1,2,5,10,20"
    3. End Sub

    Im Codebereich des Worksheet:

    Visual Basic-Quellcode

    1. ​Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    2. Dim Bar As Commandbar
    3. CellValues = Array("1", "2", "5", "10", "20")
    4. If Target.Count = 1 And Not Intersect(Selection, Columns(1)) Is Nothing Then
    5. For Each Bar In Application.CommandBars
    6. If Bar.Name = "DefaultValues" Then
    7. Bar.ShowPopup
    8. Cancel = True
    9. Exit Sub
    10. End If
    11. Next
    12. End If
    13. End Sub

    Im Codebereich eines Moduls (z.B. ContextMenu):

    Visual Basic-Quellcode

    1. ​Public CellValues
    2. Sub CreateCommandBar(ByVal Name As String, ByVal ControlNames As String)
    3. Dim Bar As Commandbar, Ctl As CommandBarControl, ControlName() As String, i As Integer
    4. CellValues = Split(ControlNames, ",")
    5. DeleteCommandBar Name
    6. Set Bar = Application.CommandBars.Add(Name, msoBarPopup, False, True)
    7. For i = LBound(CellValues) To UBound(CellValues)
    8. Set Ctl = Bar.Controls.Add(msoControlButton)
    9. Ctl.Caption = CellValues(i)
    10. Ctl.Tag = CellValues(i)
    11. Ctl.Parameter = CellValues(i)
    12. Ctl.OnAction = "On" & Name & i
    13. Next
    14. End Sub
    15. Sub DeleteCommandBar(ByVal Name As String)
    16. On Error GoTo Done
    17. CommandBars(Name).Delete
    18. Done:
    19. End Sub
    20. Sub OnDefaultValues0()
    21. OnDefaultValue (0)
    22. End Sub
    23. Sub OnDefaultValues1()
    24. OnDefaultValue (1)
    25. End Sub
    26. Sub OnDefaultValues2()
    27. OnDefaultValue (2)
    28. End Sub
    29. Sub OnDefaultValues3()
    30. OnDefaultValue (3)
    31. End Sub
    32. Sub OnDefaultValues4()
    33. OnDefaultValue (4)
    34. End Sub
    35. Sub OnDefaultValues5()
    36. OnDefaultValue (5)
    37. End Sub
    38. Private Sub OnDefaultValue(ByVal i As Integer)
    39. On Error GoTo Done
    40. Selection.Value = CellValues(i)
    41. Done:
    42. End Sub


    Ganz gefällt mir die Lösung nicht, weil ich es nicht schaffe, die Parameter des CommandBar an die Action-Routine zu übergeben.
    So benötige ich eine globale Variable und für jeden Menüpunkt eine eigene Actionroutine.

    Falls sich jemand daran austoben will und die Parameterübergabe schafft: Nur zu!
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Auch mit Application.CommandBars.ActionControl.Caption nicht?
    Oder über den Application.Caller, z.B. Application.CommandBars("DeineCommandbar").Controls(Application.Caller(2)).Controls(Application.Caller(1)).Caption
    Bei mir funktioniert es.

    Visual Basic-Quellcode

    1. Public CellValues
    2. Sub CreateCommandBar(ByVal Name As String, ByVal ControlNames As String)
    3. Dim Bar As CommandBar, Ctl As CommandBarControl, ControlName() As String, i As Integer
    4. CellValues = Split(ControlNames, ",")
    5. DeleteCommandBar Name
    6. Set Bar = Application.CommandBars.Add(Name, msoBarPopup, False, True)
    7. For i = LBound(CellValues) To UBound(CellValues)
    8. Set Ctl = Bar.Controls.Add(msoControlButton)
    9. Ctl.Caption = CellValues(i)
    10. Ctl.Tag = CellValues(i)
    11. Ctl.Parameter = CellValues(i)
    12. Ctl.OnAction = "Test"
    13. Next
    14. End Sub
    15. Sub Test()
    16. Selection.Value = Application.CommandBars.ActionControl.Caption
    17. End Sub


    Wichtig: Funktioniert nur bei Nutzung einer Maus. Bei Fingernutzung (Tablets) wird ein spezielles "Fingermenü" bereitgestellt welches sich nicht anpassen lässt. Getestet in Excel 2013.
    Danke.
    Der Ansatz über ActionControl war genau der richtige.
    Damit lässt sich das ganze auf ein Minimum begrenzen.

    Visual Basic-Quellcode

    1. Private Sub Workbook_Open()
    2. CreateCommandBar "DefaultValues", Array(1, 2, 5, 10, 20, 50, 100, 200)
    3. End Sub

    Visual Basic-Quellcode

    1. Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    2. Dim Bar As Commandbar
    3. If Target.Count = 1 And Not Intersect(Target, Columns(1)) Is Nothing Then
    4. For Each Bar In Application.CommandBars
    5. If Bar.Name = "DefaultValues" Then
    6. Bar.ShowPopup
    7. Cancel = True
    8. Exit Sub
    9. End If
    10. Next
    11. End If
    12. End Sub

    Visual Basic-Quellcode

    1. Sub CreateCommandBar(ByVal Name As String, ByVal ControlNames)
    2. Dim Bar As Commandbar, Ctl As CommandBarControl, Item
    3. Set Bar = Application.CommandBars.Add(Name, msoBarPopup, False, True)
    4. For Each Item In ControlNames
    5. Set Ctl = Bar.Controls.Add(msoControlButton)
    6. Ctl.Caption = Item
    7. Ctl.Tag = Item
    8. Ctl.Parameter = Item
    9. Ctl.OnAction = Name & "_RightClick"
    10. Next
    11. End Sub
    12. Private Sub DefaultValues_RightClick()
    13. Selection.Value = Application.CommandBars.ActionControl.Parameter
    14. End Sub
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Ich würde "ctl" als CommandBarButtoin deklarieren, damit wären auch Icons möglich.

    Visual Basic-Quellcode

    1. Private Sub Workbook_Open()
    2. CreateCommandBar "DefaultValues", "1,2,5,10,20", "3,20,4,2,11"
    3. End Sub


    Visual Basic-Quellcode

    1. Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    2. Dim cmbBar As CommandBar
    3. ControlValues = Array("1", "2", "5", "10", "20")
    4. ControlFaces = Array("3", "20", "4", "2", "11")
    5. If Target.Count = 1 And Not Intersect(Selection, Columns(1)) Is Nothing Then
    6. For Each cmbBar In Application.CommandBars
    7. If cmbBar.Name = "DefaultValues" Then
    8. cmbBar.ShowPopup
    9. Cancel = True
    10. Exit Sub
    11. End If
    12. Next cmbBar
    13. End If
    14. End Sub


    Visual Basic-Quellcode

    1. Public ControlValues
    2. Public ControlFaces
    3. Sub CreateCommandBar(ByVal Name As String, ByVal ControlNames As String, ByVal ControlFace As String)
    4. Dim cmbBar As CommandBar
    5. Dim cmbButton As CommandBarButton
    6. Dim strControlName() As String
    7. Dim lngControlCount As Long
    8. ControlValues = Split(ControlNames, ",")
    9. ControlFaces = Split(ControlFace, ",")
    10. Set cmbBar = Application.CommandBars.Add(Name:=Name, Position:=msoBarPopup, temporary:=True)
    11. On Error Resume Next
    12. For lngControlCount = LBound(ControlValues) To UBound(ControlValues)
    13. Set cmbButton = cmbBar.Controls.Add(msoControlButton)
    14. With cmbButton
    15. .Style = msoButtonIconAndCaption
    16. .Caption = ControlValues(lngControlCount)
    17. .Tag = ControlValues(lngControlCount)
    18. .Parameter = ControlValues(lngControlCount)
    19. .FaceId = ControlFaces(lngControlCount)
    20. .OnAction = "Test"
    21. End With
    22. Next lngControlCount
    23. End Sub
    24. Sub Test()
    25. Selection.Value = Application.CommandBars.ActionControl.Parameter
    26. End Sub
    Na wenigstens haben auch andere etwas davon. Kann man ja auch für Userformen nutzen, um z.B. einer Schaltfläche ein Menü zu spendieren.

    Eigentlich wollte ich ja mit Application.CommandBars.GetImageMso an die Icons (sprechende Namen sind m.E. besser als sich Zahlen merken zu müssen), aber der lässt mich nicht.

    TomWi schrieb:

    bin ich schon lange ausgestiegen
    Ist ja nicht schlimm.
    Ich versuch's mal anhand des Beispiels aus Post #15 zu erklären, da das am ehesten auf dein Bedürfnis zugeschnitten ist.
    Der erste Teil ​Workbook_Open kommt in das Workbook, in deutschen Umgebungen heisst die üblicherweise DieseArbeitsmappe.
    Das ist eine Eventroutine, die automatisch aufgerufen wird, wenn die Datei geöffnet wird.
    Hier wird der Aufruf zum Erzeugen des speziellen Kontextmenus getätigt.

    Im zweiten Teil ist ebenfalls eine Eventroutine ​Worksheet_BeforeRightClick codiert, die automatisch aufgerufen wird, wenn du einen Rechtsklick auf eine Zelle machst, aber noch bevor das Contextmenu angezeigt wird.
    Hier wird abgefragt, ob eine Einzelzelle in der ersten Spalte betroffen ist.
    Falls dies der Fall ist, wird das spezielle Menu angezeigt und das normale verworfen.

    Der dritte Teil wird in einem Modul angelegt und erzeugt mit der ersten Methode ​CreateCommandBar das Menu und seine Einträge (aufgerufen aus Workbook_Open).
    Die zweite Methode ​DefaultValues_RightClick wird aufgerufen, wenn im Kontextmenu ein Eintrag gewählt wurde und trägt dessen Wert in die aktuell aktive Zelle ein.

    Wenn du den Code verstehen willst, ist es am einfachsten, wenn du in allen Routinen einen Breakpoint setzt und im Singlestep durchgehst.
    Wobei das mit dem Breakpoint beim Workbook_Open nicht trivial ist, da zu dessen Ausführungszeit die IDE noch gar nicht offen ist.
    Du kannst das durch Codieren eines Stop als erstes Statement forcieren.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --