VBA in Excel/ Weitere unsortierte Beispiele
Belegte Zellen bestimmen
[Bearbeiten]Mit dem nachfolgenden Beispiel können die erste und letzte belegte Zelle in einer Zeile bestimmt werden. Klicken Sie eine beliebige Zeile an und starten das Makro. Ein Meldungsfenster gibt Ihnen Auskunft, welches die erste und letzte belegte Zelle der angeklickten Zeile ist.
Sub ErsteUndLetzteBelegteZelleInZeile()
Dim lngSpalte1&, lngSpalte2 As Long: Dim strAusgabetext As String
lngSpalte1 = Cells(ActiveCell.Row, 1).End(xlToRight).Column
lngSpalte2 = Cells(ActiveCell.Row, Rows(ActiveCell.Row).Cells.Count).End(xlToLeft).Column
If IsEmpty(Cells(ActiveCell.Row, 1)) = False Then lngSpalte1 = 1
strAusgabetext = Switch(lngSpalte1 = Rows(ActiveCell.Row).Cells.Count And lngSpalte2 = 1, _
"Zeile " & ActiveCell.Row & " ist leer.", lngSpalte1 >= 1 And lngSpalte2 > lngSpalte1, _
"In der angeklickten Zeile ist die erste belegte Zelle " & Cells(ActiveCell.Row, _
lngSpalte1).Address(False, False) & vbCr & " mit dem Wert " & _
Cells(ActiveCell.Row, lngSpalte1) & " und die letzte Zelle ist " & _
Cells(ActiveCell.Row, lngSpalte2).Address(False, False) & vbCr & " mit dem Wert " & _
Cells(ActiveCell.Row, lngSpalte2) & ".", lngSpalte1 = lngSpalte2, _
"Es ist nur Zelle " & Cells(ActiveCell.Row, lngSpalte1).Address(False, False) & _
" mit dem Wert " & Cells(ActiveCell.Row, lngSpalte1) & " belegt.")
MsgBox strAusgabetext, vbInformation
End Sub
Add-Ins
[Bearbeiten]Add-In installieren
Sub InstallAddIn()
Dim AddInNeu As AddIn
On Error Resume Next
Set AddInNeu = AddIns.Add(Filename:=Environ("AppData") & "\Microsoft\AddIns\neuesAddIn.xlam")
AddInNeu.Installed = True
MsgBox AddInNeu.Title & " wurde installiert."
Exit Sub
ErrorHandler:
MsgBox "An error occurred."
End Sub
Add-In deinstallieren
Sub AddinEinbinden()
Application.AddIns("neuesAddIn").Installed = False
End Sub
Add-In schließen
Sub addInSchließen()
On Error Resume Next
Workbooks("neuesAddIn.xlam").Close
End Sub
Variablentyp bestimmen
[Bearbeiten]Klicken Sie eine belegte Zelle eines Arbeitsblatts an. Mit dem Makro können Sie den Variablentyp einer Zelle bestimmen.
Sub ZellenWerttypErmitteln()
Dim strVariablentyp As String
Dim byteIndex As Byte
byteIndex = VarType(ActiveCell)
strVariablentyp = Choose(byteIndex + 1, "Empty", "Null", "Integer", "Long", _
"Single", "Double", "Currency", "Date", "String", "Object", "Error", "Boolean")
MsgBox strVariablentyp
End Sub
Arbeitsblattexistenz bestimmen
[Bearbeiten]Mit diesem Makro können Sie die Existenz eines Tabellenblatts überprüfen. Wenn Sie in die zweite Inputbox keinen Mappennamen eintragen, wird unterstelltt, dass die Existenz des eingegebenen Tabellenblatts in der aktivierten Mappe geprüft werden soll. (Beachte: der zu überprüfende BlattCodename ist nicht identisch mit dem Tabellennamen (wie auf dem Tabellenregisterblatt). Sie können den jeweiligen BlattCodenamen im Projektexplorer herausfinden. Der Blattcodename ist Tabelle1, Tabelle2 usw.) Verweis: Microsoft Visual Basic for Applications Extensibility
Function BlattDa(strBlattCodename As String, Optional Mappe As Workbook) As Boolean
If Mappe Is Nothing Then
Set Mappe = ActiveWorkbook
Else
For Each Workbook In Application.Workbooks
If Mappe.Name = Workbook.Name Then Set Mappe = Workbook
Next Workbook
End If
For Each Worksheet In Mappe.Worksheets
If Mappe.VBProject.VBComponents(Worksheet.CodeName).Name = strBlattCodename Then
BlattDa = True
End If
Next Worksheet
End Function
Sub CheckForSheet()
Dim boolBlattDa As Boolean
Dim strMappenname$
Dim strBlattCodename$
strBlattCodename = InputBox("Gebe den Blattcodenamen ein")
If strBlattCodename = "" Then Exit Sub
strMappenname = InputBox("Gebe den Namen der geöffneten Mappe ohne Dateiendung ein! " & _
"Falls Sie nichts eintragen und ok klicken, wird die aktuelle Mappe geprüft!")
If strMappenname <> "" Then
On Error Resume Next
If Workbooks(strMappenname) Is Nothing Then
MsgBox "Die Mappe ist nicht geöffnet oder existiert nicht", vbCritical
Exit Sub
End If
End If
If strMappenname = "" Then
boolBlattDa = BlattDa(strBlattCodename)
Else
boolBlattDa = BlattDa(strBlattCodename, Workbooks(strMappenname))
End If
If boolBlattDa Then
MsgBox "Das Blatt existiert!"
Else
MsgBox "The worksheet does NOT exist!"
End If
End Sub
Tabellenlisten mit Anwenderformular editieren
[Bearbeiten]Erzeugen Sie händisch oder per VBA-Makro eine Tabellenliste und fügen das erste Makro in das Codemodul des verwendeten Arbeitsblatts ein.
Danach erstellen Sie ein Anwenderformular Userform1 und platzieren darauf ein Listenfeld, drei Befehlsschaltflächen Commandbutton1 - 3 und für jede zu editierende Tabellenspalte jeweils ein Texteingabefeld Textbox.
CommandButton1 - Caption: Zeile hinzufügen CommandButton2: Caption: Zeile ändern CommandButton3: Caption: Zeile löschen Um das Makro zu starten, klicken Sie doppelt auf die Tabellenliste.
Codemodul des verwendeten Arbeitsblatts
Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim strListobjectname
On Error Resume Next
If Selection.ListObject.Name = "" Then
MsgBox "Keine Tabellenliste angeklickt"
Exit Sub
Else
strListobjectname = Selection.ListObject.Name
End If
Load UserForm1
With UserForm1
.Caption = "Verkaufsliste"
.Show
End With
End Sub
Codemodul des Anwenderformulars, Name: Userform1
Private strListobjectname$
Sub ListenfeldFüllen()
Dim i%, intSpaltenzahl%, sngSpaltenbreite!(), varSpaltenbreiten
intSpaltenzahl = ActiveSheet.ListObjects(strListobjectname).ListColumns.Count
For i = 0 To intSpaltenzahl - 1
ReDim Preserve sngSpaltenbreite(i)
sngSpaltenbreite(i) = ActiveSheet.ListObjects(strListobjectname).ListColumns(i + 1).Range.ColumnWidth
Next i
With Me
With .ListBox1
.Clear
.ListStyle = fmListStylePlain
.ColumnCount = intSpaltenzahl
.ColumnHeads = True
For i = 0 To intSpaltenzahl - 1
varSpaltenbreiten = varSpaltenbreiten & CStr(sngSpaltenbreite(i) / 5.3 & " cm;")
Next i
.Font.Size = 10.5
.ColumnWidths = varSpaltenbreiten
Call RowSourceEinstellen
End With
End With
End Sub
Sub RowSourceEinstellen()
With ListBox1
.RowSource = ActiveSheet.ListObjects(strListobjectname).Range.Address
If ActiveSheet.ListObjects(strListobjectname).Range.Rows.Count > 1 Then
.RowSource = ActiveSheet.ListObjects(strListobjectname).Range.Offset(1, 0).Resize( _
ActiveSheet.ListObjects(strListobjectname).Range.Rows.Count - 1).Address(External:=True)
End If
End With
End Sub
Private Sub CommandButton1_Click()
Dim Listzeile As ListRow, Bereich As Range, i%, j&, tb As MSForms.Control
Set Listzeile = ActiveSheet.ListObjects(strListobjectname).ListRows.Add
Set Bereich = ActiveSheet.ListObjects(strListobjectname).ListRows(Listzeile.Index).Range
i = 1: j = Listzeile.Index
For Each tb In Me.Controls
If TypeName(tb) = "TextBox" Then
Bereich(i) = tb.Text
i = i + 1
End If
If i > ActiveSheet.ListObjects(strListobjectname).ListColumns.Count Then Exit For
Next tb
Call RowSourceEinstellen
ListBox1.Selected(j - 1) = True
For Each tb In Me.Controls
If TypeName(tb) = "TextBox" Then
tb.Text = ""
End If
Next tb
End Sub
Private Sub CommandButton2_Click()
Dim i%, j&, Bereich As Range, varBereich() As Variant, tb As MSForms.Control
i = 1
If ListBox1.ListIndex = -1 Then ListBox1.Selected(0) = True
j = ListBox1.ListIndex
On Error Resume Next
Set Bereich = ActiveSheet.ListObjects(strListobjectname).ListRows(Me.ListBox1.ListIndex + 1).Range
For Each tb In Me.Controls
If TypeName(tb) = "TextBox" Then
ReDim Preserve varBereich(i)
varBereich(i) = tb.Text
i = i + 1
End If
If i > ActiveSheet.ListObjects(strListobjectname).ListColumns.Count Then Exit For
Next tb
For i = 1 To UBound(varBereich)
Bereich(i) = varBereich(i)
Next i
Call RowSourceEinstellen
ListBox1.Selected(j) = True
For Each tb In Me.Controls
If TypeName(tb) = "TextBox" Then
tb.Text = ""
End If
Next tb
End Sub
Private Sub CommandButton3_Click()
Dim i&, tb As MSForms.Control
i = ListBox1.ListIndex
On Error Resume Next
ActiveSheet.ListObjects(strListobjectname).ListRows(Me.ListBox1.ListIndex + 1).Delete
Call RowSourceEinstellen
On Error Resume Next
ListBox1.Selected(i - 1) = True
For Each tb In Me.Controls
If TypeName(tb) = "TextBox" Then
tb.Text = ""
End If
Next tb
End Sub
Private Sub ListBox1_click()
Dim i%, Bereich As Range, tb As MSForms.Control
i = 1
On Error Resume Next
Set Bereich = ActiveSheet.ListObjects(strListobjectname).ListRows(Me.ListBox1.ListIndex + 1).Range
For Each tb In Me.Controls
If TypeName(tb) = "TextBox" Then
tb.Text = Bereich(i)
i = i + 1
End If
If i > ActiveSheet.ListObjects(strListobjectname).ListColumns.Count Then Exit For
Next tb
End Sub
Private Sub UserForm_Initialize()
strListobjectname = Selection.ListObject.Name
Call ListenfeldFüllen
End Sub
Tabellenlistenzeilen scrollen
[Bearbeiten]Erzeugen Sie ein Drehfeld und erzeugen per Makro zum Testen eine Tabellenliste. Die letztgenannten Makros kopieren Sie in das Codemodul des verwendeten Arbeitsblatts.
Standardmodul
Sub SpinbuttonEinfügen()
Dim cb As OLEObject
Set cb = ActiveSheet.OLEObjects.Add(ClassType:="Forms.SpinButton.1", Link:=False, _
DisplayAsIcon:=False, Left:=413.25, Top:=86.25, Width:=28.5, Height:=33)
End Sub
Sub CreateTable()
[a1] = "Produkt": [b1] = "Verkäufer": [c1] = "Verkaufsmenge"
[a2] = "Navigation": [b2] = "Schröder": [c2] = 1
[a3] = "Handy": [b3] = "Schmied": [c3] = 10
[a4] = "Navigation": [b4] = "Müller": [c4] = 20
[a5] = "Navigation": [b5] = "Schmied": [c5] = 30
[a6] = "Handy": [b6] = "Müller": [c6] = 40
[a7] = "iPod": [b7] = "Schmied": [c7] = 50
[a8] = "Navigation": [b8] = "Schröder": [c8] = 60
[a9] = "Handy": [b9] = "Becker": [c9] = 70
[a10] = "iPod": [b10] = "Müller": [c10] = 80
On Error Resume Next
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$a$1:$c$10"), , xlYes).Name = _
"Table1"
ActiveSheet.ListObjects("Table1").TableStyle = "TableStyleLight2"
End Sub
Codemodul des Arbeitsblatts mit der Tabellenliste
Private lo As ListObject, lr As ListRow
Private lngSpinbutton1Max, lngSpinSelected&
Private Sub Worksheet_Activate()
Call Werte
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Call Werte
End Sub
Private Sub SpinButton1_SpinUp()
Call swap
End Sub
Private Sub SpinButton1_SpinDown()
Call swap
End Sub
Private Sub Werte()
If Not Intersect(ActiveCell, ListObjects(1).DataBodyRange) Is Nothing Then
SpinButton1.Max = ActiveSheet.ListObjects(Selection.ListObject.Name).ListRows.Count
SpinButton1.Min = 1
lngSpinbutton1Max = SpinButton1.Max
Set lo = ActiveSheet.ListObjects("Table1")
For Each lr In lo.ListRows
If Not Intersect(lr.Range, ActiveCell) Is Nothing Then
SpinButton1.Value = lngSpinbutton1Max + 1 - lr.Index
lngSpinSelected = lr.Index
Exit For
End If
Next lr
End If
End Sub
Private Sub swap()
Dim lngSpinNeu&
Dim ZeileNeu As Range, ZeileAlt As Range
Dim varZeileNeu As Variant, varZeileAlt As Variant, varMerkZeile
On Error Resume Next
If Not Intersect(ActiveCell, ListObjects(Selection.ListObject.Name).DataBodyRange) Is Nothing Then
lngSpinNeu = SpinButton1.Max + 1 - SpinButton1.Value
If lngSpinNeu <> lngSpinSelected Then
Set ZeileNeu = ActiveSheet.ListObjects(Selection.ListObject.Name).ListRows(lngSpinNeu).Range
Set ZeileAlt = ActiveSheet.ListObjects(Selection.ListObject.Name).ListRows(lngSpinSelected).Range
varZeileNeu = ZeileNeu
varZeileAlt = ZeileAlt
varMerkZeile = varZeileNeu
varZeileNeu = varZeileAlt
varZeileAlt = varMerkZeile
ZeileAlt = varZeileAlt
ZeileNeu = varZeileNeu
lngSpinSelected = lngSpinNeu
ActiveSheet.ListObjects(Selection.ListObject.Name).ListRows(lngSpinSelected).Range.Select
End If
End If
End Sub
Exceldaten in XML-Dokument exportieren
[Bearbeiten]Soweit mit Ihrer Office-Version XML mitgeliefert wurde, setzen Sie einen Verweis auf Microsoft XML. Dieses Makro verwendet die Version 6.0. Bei Version 5.0 verwenden Sie die Variablendeklaration Domdocument50.
Sub Excel_XML()
Dim xml As New MSXML2.domdocument60
Dim xmlKnoten As MSXML2.IXMLDOMElement
Dim xmlUnterknoten As MSXML2.IXMLDOMElement
Dim Zelle As Range, strWert$, strNeu$, i%
Cells.Clear
[a1] = "Produkt": [b1] = "Verkäufer": [c1] = "Verkaufsmenge"
[a2] = "Navigation": [b2] = "Schröder": [c2] = 1
[a3] = "Handy": [b3] = "Schmied": [c3] = 10
[a4] = "Navigation": [b4] = "Müller": [c4] = 20
[a5] = "Navigation": [b5] = "Schmied": [c5] = 30
[a6] = "Handy": [b6] = "Müller": [c6] = 40
[a7] = "iPod": [b7] = "Schmied": [c7] = 50
[a8] = "Navigation": [b8] = "Schröder": [c8] = 60
[a9] = "Handy": [b9] = "Becker": [c9] = 70
[a10] = "iPod": [b10] = "Müller": [c10] = 80
xml.LoadXML "<?xml version=""1.0"" " & " encoding=""ISO-8859-1""?><meineXMLListe/>"
For Each Row In [a2:c10].Rows
Set xmlKnoten = xml.createElement("Knoten")
For Each Zelle In [a1:c1].Columns
Zelle.Value = Replace(Zelle.Value, "ä", "ae")
Zelle.Value = Replace(Zelle.Value, "Ä", "Ae")
Zelle.Value = Replace(Zelle.Value, "ö", "oe")
Zelle.Value = Replace(Zelle.Value, "Ö", "Oe")
Zelle.Value = Replace(Zelle.Value, "ü", "ue")
Zelle.Value = Replace(Zelle.Value, "Ü", "Ue")
For i = 1 To Len(Zelle.Value)
If Mid(Zelle.Value, i, 1) Like "[a-z]" Or Mid(Zelle.Value, i, 1) Like "[A-Z]" Or _
Mid(Zelle.Value, i, 1) Like "[0-9]" Or Mid(Zelle.Value, i, 1) Like "_" Then _
strNeu = strNeu & Mid(Zelle.Value, i, 1)
Next i
Set xmlUnterknoten = xml.createElement(strNeu)
xmlKnoten.appendChild(xmlUnterknoten).Text = Cells(Row.Row, Zelle.Column).Value
strNeu = ""
Next Zelle
xml.DocumentElement.appendChild xmlKnoten
Next Row
xml.Save Environ("tmp") & "\meineXMLDatei.xml"
Set xml = Nothing: Set xmlKnoten = Nothing: Set xmlUnterknoten = Nothing
End Sub
XML-Daten in Excelblatt importieren
[Bearbeiten]Erzeugen Sie mit dem ersten Makro die Schema-Definition. Der Import erfolgt dann mit dem zweiten Makro, das die Schema-Definition verwendet.
Sub Create_XSD()
Dim strMyXml As String, meinMap As XmlMap
Dim strMeinSchema$
strMyXml = "<meineXMLListe>" & _
"<Knoten>" & _
"<Produkt>Text</Produkt>" & _
"<Verkaeufer>Text</Verkaeufer>" & _
"<Verkaufsmenge>999</Verkaufsmenge>" & _
"</Knoten>" & _
"<Knoten></Knoten>" & _
"</meineXMLListe>"
Application.DisplayAlerts = False
Set meinMap = ThisWorkbook.XmlMaps.Add(strMyXml)
Application.DisplayAlerts = True
strMeinSchema = meinMap.Schemas(1).xml
Open ThisWorkbook.Path & "\strMeinSchema.xsd" For Output As #1
Print #1, strMeinSchema
Close #1
End Sub
Sub CreateXMLList()
Dim Map1 As XmlMap
Dim objList As ListObject
Dim objColumn As ListColumn
Dim i%
If Dir(ThisWorkbook.Path & "\strMeinSchema.xsd") = "" Then Exit Sub
Set Map1 = ThisWorkbook.XmlMaps.Add(ThisWorkbook.Path & "\strMeinSchema.xsd")
On Error Resume Next
ActiveSheet.ListObjects(1).Delete
Application.DisplayAlerts = False
ActiveSheet.Range("A1").Select
Set objList = ActiveSheet.ListObjects.Add
objList.ListColumns(1).XPath.SetValue Map1, "/meineXMLListe/Knoten/Produkt"
Set objColumn = objList.ListColumns.Add
objColumn.XPath.SetValue Map1, "/meineXMLListe/Knoten/Verkaeufer"
Set objColumn = objList.ListColumns.Add
objColumn.XPath.SetValue Map1, "/meineXMLListe/Knoten/Verkaufsmenge"
objList.ListColumns(1).Name = "Produkt"
objList.ListColumns(2).Name = "Verkäufer"
objList.ListColumns(3).Name = "Verkaufsmenge"
Columns.AutoFit
Application.DisplayAlerts = False
Map1.Import (Environ("tmp") & "\meineXMLDatei.xml")
End Sub
oder:
Standardmodul
Public Sub GetOverwrite()
Dim clsOverwrite As New Klasse1
Cells.Clear
On Error Resume Next
clsOverwrite.GetXMLData
End Sub
Klassenmodul, Name: Klasse1
Public Function GetXMLData() As Variant
Dim strXmlQuelldatei$
Dim XmlImportResult As XlXmlImportResult
strXmlQuelldatei = Environ("tmp") & "\meineXMLDatei.xml"
If Dir(strXmlQuelldatei) = vbNullString Then MsgBox "Die Quelldatei wurde nicht gefunden"
XmlImportResult = ActiveWorkbook.XmlImport(strXmlQuelldatei, Nothing, _
True, ActiveCell)
If XmlImportResult = xlXmlImportSuccess Then MsgBox "XML Datenimport komplett"
End Function
Exceldaten in Access-Datenbank exportieren
[Bearbeiten]Sub neueDatenbankErzeugen()
Dim cat As New ADOX.Catalog
Dim tbl As New ADOX.Table
Dim strPfad$
strPfad = Environ("localAPPDATA") & "\microsoft\office\pivotTabelle.accdb"
If Dir(strPfad) = "" Then _
cat.Create "Provider = microsoft.ace.oledb.12.0; data source=" & strPfad
With tbl
.ParentCatalog = cat
.Name = "Früchteverkauf"
With .Columns
.Append "Frucht", adVarWChar, 60
.Append "Monat", adVarWChar, 10
.Append "Menge", adInteger
End With
.Columns("Menge").Properties("Nullable") = True
End With
cat.Tables.Append tbl
Set tbl = Nothing
Set cat = Nothing
End Sub
Sub DatenHinzufügenADO()
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim Row As Range, Column As Range
Dim strPfad$
strPfad = Environ("localAPPDATA") & "\microsoft\office\pivotTabelle.accdb"
If Dir(strPfad) = "" Then Exit Sub
With ActiveSheet
.Cells.Clear
.[a1] = "Frucht": .[B1] = "Jan.": .[C1] = "Feb.": .[D1] = "Mär."
.[A2] = "Äpfel": .[B2] = 5: .[C2] = 3: .[D2] = 4
.[a3] = "Orangen": .[B3] = 4: .[D3] = 5
.[A4] = "Birnen": .[B4] = 2: .[C4] = 3: .[D4] = 5
conn.Open "Provider=Microsoft.ace.OLEDB.12.0;" & _
"Data Source=" & strPfad
End With
With rs
.Open "Früchteverkauf", conn, adOpenKeyset, adLockOptimistic
For Each Row In ActiveSheet.[2:4].Rows
For Each Column In ActiveSheet.[b:d].Columns
.AddNew
!Frucht = ActiveSheet.Cells(Row.Row, 1)
!Monat = ActiveSheet.Cells(1, Column.Column)
!Menge = ActiveSheet.Cells(Row.Row, Column.Column)
.Update
Next Column
Next Row
.Close
End With
Set rs = Nothing: Set conn = Nothing
End Sub
Pivottabelle aus Accessdatenbank erstellen
[Bearbeiten]Sub CreatePivotTableADO()
Dim PivotC As PivotCache
Dim PivotT As PivotTable
Dim strSQL$
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
conn.Open "Provider=Microsoft.ace.OLEDB.12.0;" & "Data Source=" & _
Environ("localAPPDATA") & "\microsoft\office\pivotTabelle.accdb"
rs.Open "Früchteverkauf", conn, adOpenKeyset, adLockOptimistic
If rs.RecordCount = 0 Then MsgBox ("Keine Datensätze gefunden!"), vbCritical
ActiveWindow.DisplayGridlines = False
Set PivotC = ActiveWorkbook.PivotCaches.Create(SourceType:=xlExternal)
Set PivotC.Recordset = rs
Worksheets.Add Before:=Sheets(1)
Set PivotT = ActiveSheet.PivotTables.Add(PivotCache:=PivotC, _
TableDestination:=ActiveSheet.Range("a3"))
With PivotT
.NullString = "0"
.AddFields RowFields:="Frucht", ColumnFields:="Monat"
.PivotFields("Menge").Orientation = xlDataField
End With
Set rs = Nothing
Set conn = Nothing
Set PivotT = Nothing
Set PivotC = Nothing
End Sub
Formula Array
[Bearbeiten]Wechseln im Menü Excel-Option/ Formeln zum S1Z1-Bezugsstil.
Das Makro erzeugt für einen Test eine Tabellenliste. Geben Sie in die Inputboxen einen Verkäufernamen und einen Produktnamen ein. Als Ergebnis erhalten Sie zunächst eine Information, welche Gesamtmenge des Produkts der Verkäufer insgesamt veräußert hat. Darüber hinaus wird Auskunft gegeben, um wieviele Tabellenpositionen es geht. Geben Sie für einen Test den Verkäufernamen Schröder und den Produktnamen Navigation ein!
Sub testMich()
Dim strProdukt$
Dim strVerkäufer
Dim strSpalte1
Dim strSpalte2
Dim strSpalte3
Dim Bereich1 As Range
Dim Bereich2 As Range
Dim Zelle As Range
Dim bool As Boolean
With ActiveSheet
.Cells.Clear
.ListObjects.Add(xlSrcRange, Range("$a$1:$c$10"), , xlYes).Name = "Table1"
.ListObjects("Table1").TableStyle = "TableStyleLight2"
.[a1] = "Produkt": .[b1] = "Verkäufer": .[c1] = "Verkaufsmenge"
.[a2] = "Navigation": .[b2] = "Schröder": .[c2] = 1
.[a3] = "Handy": .[b3] = "Schmied": .[c3] = 10
.[a4] = "Navigation": .[b4] = "Müller": .[c4] = 20
.[a5] = "Navigation": .[b5] = "Schmied": .[c5] = 30
.[a6] = "Handy": .[b6] = "Müller": .[c6] = 40
.[a7] = "iPod": .[b7] = "Schmied": .[c7] = 50
.[a8] = "Navigation": .[b8] = "Schröder": .[c8] = 60
.[a9] = "Handy": .[b9] = "Becker": .[c9] = 70
.[a10] = "iPod": .[b10] = "Müller": .[c10] = 80
strSpalte1 = ActiveSheet.ListObjects("Table1").DataBodyRange.Columns(1).Address(False, False)
strSpalte2 = ActiveSheet.ListObjects("Table1").DataBodyRange.Columns(2).Address(False, False)
strSpalte3 = ActiveSheet.ListObjects("Table1").DataBodyRange.Columns(3).Address(False, False)
Set Bereich1 = Range(strSpalte1)
Set Bereich2 = Range(strSpalte2)
strProdukt = InputBox("Gebe das Produkt ein!")
If strProdukt = "" Then Exit Sub
For Each Zelle In Bereich1
If Zelle.Value = strProdukt Then bool = True
Next Zelle
If bool = False Then
MsgBox "Der eingegebene Produktname existiert nicht oder ist falsch", vbInformation
Exit Sub
End If
bool = False
strVerkäufer = InputBox("Gebe den Verkäufer ein!")
If strVerkäufer = "" Then Exit Sub
For Each Zelle In Bereich2
If Zelle.Value = strVerkäufer Then bool = True
Next Zelle
If bool = False Then
MsgBox "Der eingegebene Verkäufername existiert nicht oder ist falsch", vbInformation
Exit Sub
End If
.[e9] = "Gesamte Verkaufsmenge " & strProdukt & " durch Verkäufer " & strVerkäufer
.[e10].FormulaArray = "=SUM((" & strSpalte1 & "= """ & strProdukt & """)*(" & strSpalte2 & "=""" & strVerkäufer & """)*(" & strSpalte3 & "))"
.[e12] = "Anzahl der Verkaufspositionen des Produkts " & strProdukt & " duch den Verkäufer " & strVerkäufer 'logischen UND letztlich aber ANZAHL der Zeilen mit Navigation von Schröder ---works---
.[e13].FormulaArray = "=SUM((" & strSpalte1 & "= """ & strProdukt & """)*(" & strSpalte2 & " = """ & strVerkäufer & """))"
End With
End Sub
Bedingte Formatierung
[Bearbeiten]Dieses Beispiel erzeugt anhand einer Beispieltabelle mit bedingter Formatierung Richtungspfeile, die abhängig vom Trend in eine bestimmte Richtung zeigen.
Sub SetConditionalFormatting()
Dim cfIconSet As IconSetCondition: Dim Bool As Boolean
For Each Worksheet In ThisWorkbook.Worksheets
If Worksheet.Name = "Bedingte Formatierung" Then Bool = True
Next Worksheet
If Bool = False Then Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "Bedingte Formatierung"
With Sheets("Bedingte Formatierung")
.Cells.Clear
.Range("C1").Value = -0.01: .Range("C6").Value = 0
.Range("C2").Value = 0.005: .Range("C7").Value = 0
.Range("C3").Value = -0.02: .Range("C8").Value = 0.005
.Range("C4").Value = -0.02: .Range("C9").Value = -0.02
.Range("C5").Value = 0.005: .Range("C10").Value = 0.005
.Range("C1", "C10").NumberFormat = " 0.00 ;[Red] - 0.00 "
Set cfIconSet = .Range("C1", "C10").FormatConditions.AddIconSetCondition
.Range("C1", "C10").FormatConditions(1).SetFirstPriority
End With
cfIconSet.IconSet = ActiveWorkbook.IconSets(xl3Arrows)
With cfIconSet.IconCriteria(2)
.Type = xlConditionValueNumber
.Value = 0
.Operator = 7
End With
With cfIconSet.IconCriteria(3)
.Type = xlConditionValueNumber
.Value = 0.0001
.Operator = 7
End With
Set cfIconSet = Nothing
End Sub
Zellengroße Diagramme in Arbeitsblatt einfügen
[Bearbeiten]Dieses Beispiel erzeugt anhand einiger Testdaten zellengroße Säulendiagramme.
Sub addTinyCharts()
Dim Bereich As Range
Dim i As Integer
With ActiveSheet
Set Bereich = .[b2:m4]
For i = .ChartObjects.Count To 1 Step -1
.ChartObjects(i).Delete
Next i
.[a1] = "Frucht": .[B1] = "Jan.": .[C1] = "Feb.": .[D1] = "Mär.": .[E1] = "Apr.": .[f1] = "Mai": .[g1] = "Jun.": .[h1] = "Jul.": .[i1] = "Aug.": .[j1] = "Sep.": .[k1] = "Okt.": .[l1] = "Nov.": .[m1] = "Dez.": .[n1] = "Gesamt"
.[A2] = "Ananas": .[B2] = 5: .[C2] = 3: .[D2] = 4: .[e2] = 4: .[f2] = 4: .[g2] = 4: .[h2] = 4: .[i2] = 4: .[j2] = 4: .[k2] = 4: .[l2] = 4: .[m2] = 4
.[a3] = "Kiwi": .[B3] = 45: .[C3] = 78: .[D3] = 78: .[e3] = 78: .[f3] = 98: .[g3] = 88: [h3] = 4: .[i3] = 4: .[j3] = 4: .[k3] = 8: .[l3] = 69: .[m3] = 96
.[A4] = "Papaya": .[B4] = 54: .[C4] = 27: .[D4] = 33: .[e4] = 82: .[f4] = 4: .[g4] = 4: .[h4] = 4: .[i4] = 4: .[j4] = 51: .[k4] = 10: .[l4] = 4: .[m4] = 10
.[n2].Formula = "=Sum(b2:m2)"
.[n2].AutoFill .Range("n2:n4"), xlFillDefault
End With
For Each Row In Bereich.Rows
ActiveSheet.Shapes.AddChart.Select
With ActiveChart
.ChartType = xlColumnClustered
.SetSourceData Source:=Row
.HasLegend = False
.HasTitle = False
.Axes(xlCategory, xlPrimary).HasTitle = False
.Axes(xlValue, xlPrimary).HasTitle = False
.HasAxis(xlCategory, xlPrimary) = False
.HasAxis(xlValue, xlPrimary) = False
.Axes(xlValue).MajorGridlines.Delete
.Axes(xlValue).MinorGridlines.Delete
.Axes(xlCategory).MajorGridlines.Delete
.Axes(xlCategory).MinorGridlines.Delete
.SeriesCollection(1).Interior.ColorIndex = 37
.SeriesCollection(1).Border.ColorIndex = 25
.Parent.Top = ActiveSheet.Cells(Row.Row, 15).Top + 1
.Parent.Left = ActiveSheet.Cells(Row.Row, 15).Left + 1
.Parent.Height = ActiveSheet.Cells(Row.Row, 15).Height - 2
.Parent.Width = ActiveSheet.Cells(Row.Row, 15).Width - 2
.Parent.Border.ColorIndex = xlNone
.PlotArea.Top = 0
.PlotArea.Left = 0
.PlotArea.Height = .Parent.Height
.PlotArea.Width = .Parent.Width
.ChartGroups(1).GapWidth = 50
End With
Next Row
End Sub
Datensatzkollektion anlegen
[Bearbeiten]Datensätze lassen sich in Datenfelder (Arrays) kopieren. Allerdings ist dann eine flexible Handhabung der Datensätze kaum möglich. Insofern besteht die bessere Alternative, mit Klassenmodulen zu arbeiten und Kollektionen anzulegen.
Beachte: Kopieren Sie die letzten beiden Makros nicht in ein Standard- sondern in ein Klassenmodul. Benennen Sie die im Beispiel genannten Klassenmodule jeweils im Eigenschaftenfenster mit clsKontakt und clsKontakte.
Folgendes Makro wäre möglich:
Option Base 1
Type Anwenderkontaktdaten
LfdNr As String
Nachname As String * 25
HerrFrau As Boolean
Fon As String * 25
End Type
Sub ArrayFüllen()
Dim PersAngaben() As Anwenderkontaktdaten
Dim i As Integer
[a1] = "Lfdnr": [b1] = "Nachname": [c1] = "HerrFrau": [d1] = "Fon"
[a2] = "1": [b2] = "Becker": [c2] = "False": [d2] = "123"
[a3] = "2": [b3] = "Becher": [c3] = "True": [d3] = "234"
[a4] = "3": [b4] = "Bäcker": [c4] = "0": [d4] = "456"
For i = 2 To ActiveSheet.UsedRange.Rows.Count
ReDim Preserve PersAngaben(i)
PersAngaben(i).LfdNr = Cells(i, 1)
PersAngaben(i).Nachname = Cells(i, 2)
PersAngaben(i).HerrFrau = Cells(i, 3)
PersAngaben(i).Fon = Cells(i, 4)
Next i
MsgBox "Funktionstest: Im ersten Datensatz " & _
"steht der Wert " & PersAngaben(2).LfdNr, vbInformation
End Sub
Besser ist folgende Variante:
Standardmodul:
option explicit
Sub TestKontakteClass()
Dim Kontakt As clsKontakt
Dim Kontakte As New clsKontakte
Dim i As Integer
[a1] = "Lfdnr": [b1] = "Nachname": [c1] = "HerrFrau": [d1] = "Fon"
[a2] = "1": [b2] = "Becker": [c2] = "False": [d2] = "123"
[a3] = "2": [b3] = "Becher": [c3] = "True": [d3] = "234"
[a4] = "3": [b4] = "Bäcker": [c4] = "0": [d4] = "456"
For i = 2 To ActiveSheet.[a1].CurrentRegion.Rows.Count
Set Kontakt = New clsKontakt
Kontakt.LfdNr = ActiveSheet.Cells(i, 1)
Kontakt.Nachname = ActiveSheet.Cells(i, 2)
Kontakt.HerrFrau = CBool(ActiveSheet.Cells(i, 3))
Kontakt.Fon = ActiveSheet.Cells(i, 4)
Kontakte.Add Kontakt
Next i
Kontakte.Remove 2
MsgBox "Nachdem der Kontakt Nr. 2 gelöscht wurde," & _
"beträgt die Anzahl der Kontakte " & Kontakte.Count & "." & vbCr & _
"Jetzt hat der zweite Kontakt die laufende Nummer " & Kontakte.Item(2).LfdNr & "."
Set Kontakte = Nothing
End Sub
Klassenmodul, Name: "clsKontakt"
Option Explicit
Dim pLfdNr As String
Dim pNachname As String
Dim pHerrFrau As Boolean
Dim pFon As String
Public KontaktID As String
Public Property Get LfdNr() As String
LfdNr = pLfdNr
End Property
Public Property Let LfdNr(strLfdNr As String)
pLfdNr = strLfdNr
End Property
Public Property Get Nachname() As String
Nachname = pNachname
End Property
Public Property Let Nachname(strNachname As String)
pNachname = strNachname
End Property
Public Property Get HerrFrau() As Boolean
HerrFrau = pHerrFrau
End Property
Public Property Let HerrFrau(boolHerrFrau As Boolean)
pHerrFrau = boolHerrFrau
End Property
Public Property Get Fon() As String
Fon = pFon
End Property
Public Property Let Fon(strFon As String)
pFon = strFon
End Property
Klassenmodul, Name: "clsKontakte"
Option Explicit
Private KontakteP As Collection
Public Property Get Count() As Long
Count = KontakteP.Count
End Property
Public Function Item(Index As Variant) As clsKontakt
Set Item = KontakteP(Index)
End Function
Public Sub Add(Kontakt As clsKontakt)
On Error GoTo AddError
KontakteP.Add Kontakt
Exit Sub
AddError:
Err.Raise Number:=vbObjectError + 514, Source:="clsKontakte.Add", _
Description:="Unable to Add clsKontakt object to the collection"
End Sub
Public Sub Remove(ByVal Index As Integer)
On Error GoTo RemoveError
KontakteP.Remove Index
Exit Sub
RemoveError:
Err.Raise Number:=vbObjectError + 515, Source:="clsKontakte.Remove", _
Description:="Das clsCell object kann nicht von der Kollektion gelöscht werden!"
End Sub
Private Sub Class_Initialize()
Set KontakteP = New Collection
End Sub
Private Sub Class_Terminate()
Set KontakteP = Nothing
End Sub