Takole, od zadnjič sem celo vso stvar malce nadgradil in sedaj lahko z veseljem povem, da deluje iskanje kot se spodobi. Poleg tega, sem dodal kopiranje podatkov v nov excelov dokument, brisanje rezultatov,... Malce pa sem dodelal tudi sam obrazec za iskanje in sedaj izgleda tako:
Iskalno okno se avtomatsko zažene ob zagonu Excelove datoteke. To storimo z ukazom:
Private Sub Workbook_Open()
UserForm1.Show
End Sub
Ukaz vnesemo tako, da v VBA-ju dvakrat kliknemo ThisWorkBook v VBAProject in potem iz padnih menijev izberemo: Workbook in Open.
Ostalo kodo vnesemo v obrazec. Izgleda pa tako:
Private Sub CmdIsci_Click()
'spuca vse podatke na listu
List1.Cells.Clear
With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
"ODBC;DATABASE=zzzzz;DRIVER={MySQL ODBC 3.51 Driver};OPTION=0;;PORT=0;SERVER=xxx.xxx.x.xx;UID=XXX;PASSWORD=YYY" _
, Destination:=Range("$A$1")).QueryTable
.CommandText = Array( _
"SELECT inkasso_2010_om_odvpr_0.OM, inkasso_2010_om_odvpr_0.OM_NAZIV AS 'NAZIV', inkasso_2010_obcine_odvpr_0.OBCINA_NAZIV AS 'OBČINA', inkasso_2010_sif_kraj_sk_odvpr_0.KRAJ_SK_NAZIV AS 'NASELJE', inkas" _
, _
"so_2010_sif_ulic_odvpr_0.ULICA_NAZIV AS 'ULICA', CONCAT(inkasso_2010_om_odvpr_0.OM_HS,inkasso_2010_om_odvpr_0.OM_HSD) AS 'Hst', inkasso_2010_om_posode_odvpr_0.POSODE_ODPADEK AS 'FRAKCIJA', inkasso_201" _
, _
"0_posode_odvpr_0.POSODA_VOLUMEN AS 'VOL', inkasso_2010_om_posode_odvpr_0.POSODE_FREKVENCA AS 'FREK', inkasso_2010_om_posode_odvpr_0.POSODE_IDENTST AS 'INVENTARNA', inkasso_2010_om_pogodbe_odvpr_0.POGO" _
, _
"DBA_STEVILKA AS 'POGODBA'" & Chr(13) & "" & Chr(10) & "FROM sezana.inkasso_2010_obcine_odvpr inkasso_2010_obcine_odvpr_0, sezana.inkasso_2010_om_odvpr inkasso_2010_om_odvpr_0, sezana.inkasso_2010_om_pogodbe_odvpr inkasso_2010_om" _
, _
"_pogodbe_odvpr_0, sezana.inkasso_2010_om_posode_odvpr inkasso_2010_om_posode_odvpr_0, sezana.inkasso_2010_posode_odvpr inkasso_2010_posode_odvpr_0, sezana.inkasso_2010_sif_kraj_sk_odvpr inkasso_2010_s" _
, _
"if_kraj_sk_odvpr_0, sezana.inkasso_2010_sif_ulic_odvpr inkasso_2010_sif_ulic_odvpr_0" & Chr(13) & "" & Chr(10) & "WHERE inkasso_2010_om_odvpr_0.OM = inkasso_2010_om_posode_odvpr_0.OM AND inkasso_2010_om_odvpr_0.KRAJ_SK_SIFRA = i" _
, _
"nkasso_2010_sif_kraj_sk_odvpr_0.KRAJ_SK_SIFRA AND inkasso_2010_om_odvpr_0.ULICA_SIFRA = inkasso_2010_sif_ulic_odvpr_0.ULICA_SIFRA AND inkasso_2010_om_odvpr_0.OM = inkasso_2010_om_pogodbe_odvpr_0.OM AN" _
, _
"D inkasso_2010_om_odvpr_0.OBCINA_SIFRA = inkasso_2010_obcine_odvpr_0.OBCINA_SIFRA AND inkasso_2010_om_pogodbe_odvpr_0.POGODBA_STEVILKA = inkasso_2010_om_posode_odvpr_0.POGODBA_STEVILKA AND inkasso_201" _
, _
"0_om_posode_odvpr_0.POSODA_SIFRA = inkasso_2010_posode_odvpr_0.POSODA_SIFRA AND ((inkasso_2010_om_pogodbe_odvpr_0.POGODBA_AKTIVNA='T') AND (inkasso_2010_om_posode_odvpr_0.POSODE_ZARACUNLJIVOST=2) AND " _
, "(inkasso_2010_om_odvpr_0.OM_AKTIVEN='T'))" _
, _
" AND inkasso_2010_om_odvpr_0.OM LIKE '%" & UserForm1.TxtOm.Text & "%' AND inkasso_2010_om_odvpr_0.OM_NAZIV LIKE '%" & UserForm1.TxtNaziv.Text & "%' AND inkasso_2010_obcine_odvpr_0.OBCINA_NAZIV LIKE '%" & UserForm1.TxtObcina.Text & "%'", _
" AND inkasso_2010_sif_kraj_sk_odvpr_0.KRAJ_SK_NAZIV LIKE '%" & UserForm1.TxtNaselje.Text & "%' AND inkasso_2010_sif_ulic_odvpr_0.ULICA_NAZIV LIKE '%" & UserForm1.TxtUlica.Text & "%' AND inkasso_2010_om_odvpr_0.OM_HS LIKE '%" & UserForm1.TxtHisna.Text & "%'", _
" AND inkasso_2010_om_odvpr_0.OM_HSD LIKE '%" & UserForm1.TxtDod.Text & "%' AND inkasso_2010_om_posode_odvpr_0.POSODE_ODPADEK LIKE '%" & UserForm1.TxtFrakcija.Text & "%' AND inkasso_2010_om_posode_odvpr_0.POSODE_IDENTST LIKE '%" & UserForm1.TxtInventarna.Text & "%' AND inkasso_2010_om_posode_odvpr_0.POGODBA_STEVILKA LIKE '%" & UserForm1.txtPogodba.Text & "%'" _
)
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.ListObject.DisplayName = "Tabela_izpis"
.Refresh BackgroundQuery:=False
End With
End Sub
Private Sub cmdKopiraj_Click()
ActiveWorkbook.Sheets(1).Activate
Range("A1:J1, Tabela_izpis").Select
Selection.Copy
Workbooks.Add
ActiveWorkbook.Sheets(1).Activate
ActiveSheet.Cells(1, 1).PasteSpecial
End Sub
Private Sub cmdNovo_Click()
Workbooks("iskanje_sql.xlsm").Activate
End Sub
Private Sub CommandButton1_Click()
List1.Cells.Clear
End Sub
torek, 28. junij 2011
sreda, 15. junij 2011
VBA in SQL
Živimo, baje, v času recesije, zato je potrebno včasih kakšno stvar narediti po težji poti. Ena od takih, se mi je zgodila nekaj dni nazaj. Gre sicer za precej banalen primer, ki bi se ga dalo preprosto rešiti s pomočjo MS Accessa ali pa bi se preprosto programerjem plačalo, da naredijo poročilo v trenutne programu. No, ničesar od tega ni bilo, zato sem se držal reka: "pomagaj si sam in bog ti bo pomagal".
Opis problema
Program za vodenje katastrov temelji na bazi MySql, vendar nima pripravljenih določenih izpisov. Z uporabo Excela lahko sicer naredimo query, a se pri malo manj ukih uporabnikih zatakne pri nastavljanju parametrov izpisa. Navadno pride do tega, da kliknejo na bližnjico za zagon poizvedbe in potem pobrišejo vse nepotrebne vrstice (mogoče celo stolpce). Tukaj pa nam pride hitro v pomoč VBA.
Celotna skripta še ni dodelana, ampa za prvo silo deluje. Sestavljena je iz preprostega obrazca s tremi besedilnimi polji (TextBox) in dveh gumbov.
Nato pa seveda dodamo še malo besedila, ki bo naredilo nekaj pametnega.
Za gum "Išči" sledi naslednje:
Private Sub CommandButton1_Click()
'Spucamo vse podatke na delovnem listu
List1.Cells.Clear
'povezemo se z MySQL bazo
'ce dopisemo ;PASSWORD=xxxxxx;, ne rabimo vpisovat gesla po zagonu skripte
With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
"ODBC;DATABASE=komunala;DRIVER={MySQL ODBC 3.51 Driver};OPTION=0;;PORT=0;UID=danijel;" _
, Destination:=Range("$A$1")).QueryTable
.CommandText = Array( _
"SELECT bass_pogodbe_0.ID, bass_pogodbe_0.OBCINA_SIFRA, bass_pogodbe_0.OBCINA_NAZIV, bass_pogodbe_0.KRAJ_SK_SIFRA, bass_pogodbe_0.KRAJ_SK_NAZIV, bass_pogodbe_0.ULICA_SIFRA, bass_pogodbe_0.ULICA_NAZIV, " _
, _
"bass_pogodbe_0.OM_HS, bass_pogodbe_0.OM_HSD, bass_pogodbe_0.OM, bass_pogodbe_0.OM_NAZIV, bass_pogodbe_0.OM_PLACNIK, bass_pogodbe_0.NAZIV, bass_pogodbe_0.NASLOV, bass_pogodbe_0.PTT, bass_pogodbe_0.KRAJ" _
, _
", bass_pogodbe_0.POGODBA_STEVILKA" & Chr(13) & "" & Chr(10) & "FROM komunala.bass_pogodbe bass_pogodbe_0" & Chr(13) & "" & Chr(10) & _
'pa se pogoji, ki se nanasajo na textboxe
"WHERE (bass_pogodbe_0.ULICA_NAZIV LIKE '%" & UserForm1.txtUlica.Text & "%' AND bass_pogodbe_0.OBCINA_SIFRA LIKE '%" & UserForm1.txtObcina.Text & "%' AND bass_pogodbe_0.OM_NAZIV LIKE '%" & UserForm1.txtOmNaziv.Text & "%' )")
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.ListObject.DisplayName = "Tabela_Poizvedba_iz_mysql"
.Refresh BackgroundQuery:=False
End With
End Sub
Z drugim gumbom natisnemo vsebino lista:
Private Sub CommandButton2_Click()
To je nekako osnovno, kar je bilo narejeno. Po željah in zmožnostih, bomo pa dodajali tudi nove stvari.
Opis problema
Program za vodenje katastrov temelji na bazi MySql, vendar nima pripravljenih določenih izpisov. Z uporabo Excela lahko sicer naredimo query, a se pri malo manj ukih uporabnikih zatakne pri nastavljanju parametrov izpisa. Navadno pride do tega, da kliknejo na bližnjico za zagon poizvedbe in potem pobrišejo vse nepotrebne vrstice (mogoče celo stolpce). Tukaj pa nam pride hitro v pomoč VBA.
Celotna skripta še ni dodelana, ampa za prvo silo deluje. Sestavljena je iz preprostega obrazca s tremi besedilnimi polji (TextBox) in dveh gumbov.
Nato pa seveda dodamo še malo besedila, ki bo naredilo nekaj pametnega.
Za gum "Išči" sledi naslednje:
Private Sub CommandButton1_Click()
'Spucamo vse podatke na delovnem listu
List1.Cells.Clear
'povezemo se z MySQL bazo
'ce dopisemo ;PASSWORD=xxxxxx;, ne rabimo vpisovat gesla po zagonu skripte
With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
"ODBC;DATABASE=komunala;DRIVER={MySQL ODBC 3.51 Driver};OPTION=0;;PORT=0;UID=danijel;" _
, Destination:=Range("$A$1")).QueryTable
.CommandText = Array( _
"SELECT bass_pogodbe_0.ID, bass_pogodbe_0.OBCINA_SIFRA, bass_pogodbe_0.OBCINA_NAZIV, bass_pogodbe_0.KRAJ_SK_SIFRA, bass_pogodbe_0.KRAJ_SK_NAZIV, bass_pogodbe_0.ULICA_SIFRA, bass_pogodbe_0.ULICA_NAZIV, " _
, _
"bass_pogodbe_0.OM_HS, bass_pogodbe_0.OM_HSD, bass_pogodbe_0.OM, bass_pogodbe_0.OM_NAZIV, bass_pogodbe_0.OM_PLACNIK, bass_pogodbe_0.NAZIV, bass_pogodbe_0.NASLOV, bass_pogodbe_0.PTT, bass_pogodbe_0.KRAJ" _
, _
", bass_pogodbe_0.POGODBA_STEVILKA" & Chr(13) & "" & Chr(10) & "FROM komunala.bass_pogodbe bass_pogodbe_0" & Chr(13) & "" & Chr(10) & _
'pa se pogoji, ki se nanasajo na textboxe
"WHERE (bass_pogodbe_0.ULICA_NAZIV LIKE '%" & UserForm1.txtUlica.Text & "%' AND bass_pogodbe_0.OBCINA_SIFRA LIKE '%" & UserForm1.txtObcina.Text & "%' AND bass_pogodbe_0.OM_NAZIV LIKE '%" & UserForm1.txtOmNaziv.Text & "%' )")
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.ListObject.DisplayName = "Tabela_Poizvedba_iz_mysql"
.Refresh BackgroundQuery:=False
End With
End Sub
Z drugim gumbom natisnemo vsebino lista:
Private Sub CommandButton2_Click()
With ActiveSheet.PageSetup
.PrintTitleRows = "$1:$1"
.PrintTitleColumns = ""
End With
Application.Dialogs(xlDialogPrint).Show
End Sub
To je nekako osnovno, kar je bilo narejeno. Po željah in zmožnostih, bomo pa dodajali tudi nove stvari.
petek, 15. april 2011
Obrazec za vnos
Excel je zelo uporaben ko se soočimo z vnosom podatkov. Uporabimo lahko vgrajen obrazec, lahko pa si seveda izdelamo svojega. Vse skupaj je zelo preprosto in velikokrat nam precej olajša delo.
Kot vedno zaženemo VBA (Alt+F11) in vstavimo obrazec (Insert -> UserForm). Najprej se nam prikaže samo ozadje obrazca, ki ga oblikujemo po želji; vstavimo Tekstovna polja (textbox), gumbe (button), Imena (label),...
V naslednjem primeru je prikazana izdelava obrazca za vnos podatkov o prometni signalizaciji v določenem naselju.
Sama oblika obrazca je dokaj preprosta in pregledna, ker se mi ni dalo preveč ukvarjati z lepotičenjem.
Ko zaključimo z oblikovanjem obrazca, pa je potrebno dodati tudi nekaj programske kode, ki poskrbi, da postane obrazec uporaben. V oknu Project Explorer (na zgornji sliki je to levo zgornje okno) poiščemo naš obrazec (UserForm1), kliknemo nanj z desno tipko in izberemo View Code.
Vpišemo kodo, ki naj se izvede:
Private Sub Initialize()
'ob zagonu pobrišemo vsa polja v obrazcu.
txtOdsek.Value = ""
txtOznaka.Value = ""
txtNaziv.Value = ""
txtStacionaza = ""
txtVisina = ""
txtOpomba = ""
End Sub
Private Sub cmdIzhod_Click()
'gumb za izhod zapre obrazec
Unload Me
End Sub
Private Sub cmdVnos_Click()
'ko kliknemo na gumb vnos, naj se vsebina obrazca vnese v prvo prazno vrstico
'na delovnem listu "podatki"
ActiveWorkbook.Sheets("podatki").Activate
Range("A1").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtOdsek.Value
ActiveCell.Offset(0, 1) = txtOznaka.Value
ActiveCell.Offset(0, 2) = txtNaziv.Value
ActiveCell.Offset(0, 3) = txtStacionaza.Value
ActiveCell.Offset(0, 4) = txtVisina.Value
ActiveCell.Offset(0, 5) = txtOpomba.Value
'Range("A1").Select
ActiveCell.Offset(1, 0).Select
End Sub
In zaženemo s tipko F5 ali pa kliknemo na Run -> Run Sub/User Form.
torek, 15. marec 2011
Povprečje, min, max
Danes pa nekaj, kar sploh ni bilo narejeno s pomočjo VBA. Gre za kombinacijo uporaba funkcije IF in AVERAGE.
Težava, ki je iskala rešitev, je bila v tem, da so podatki lahko v 1 ali pa več stolpcev. Ker je maksimalno število stolpcev znano, sem vse skupaj naredil bolj po partizansko; samo da dela.
Glava poročila je vedno enaka in v celicah D26 do M26 je potrebno izračunat povprečje vrednosti. Ampak. Ne vemo koliko vrstic podatkov, pa tudi vsi stolpci nimajo vedno podatkov (senzor mrtev). Torej vedno preverimo, če je v dotični celici sploh zapisana vrednost, izračunamo povprečje za tisto število celic, ki imajo številske podatke. Če pa podatkov ni, se v poročilni tabeli izpiše "Ni podatkov".
=IF(N30<>0;AVERAGE(N30:(INDEX(N30:N27201; COUNT(N30:N27201))));"Ni podatkov")
Vse skupaj je dejansko preprosto kot znana srbska nacionalna jed.
Težava, ki je iskala rešitev, je bila v tem, da so podatki lahko v 1 ali pa več stolpcev. Ker je maksimalno število stolpcev znano, sem vse skupaj naredil bolj po partizansko; samo da dela.
Glava poročila je vedno enaka in v celicah D26 do M26 je potrebno izračunat povprečje vrednosti. Ampak. Ne vemo koliko vrstic podatkov, pa tudi vsi stolpci nimajo vedno podatkov (senzor mrtev). Torej vedno preverimo, če je v dotični celici sploh zapisana vrednost, izračunamo povprečje za tisto število celic, ki imajo številske podatke. Če pa podatkov ni, se v poročilni tabeli izpiše "Ni podatkov".
=IF(N30<>0;AVERAGE(N30:(INDEX(N30:N27201; COUNT(N30:N27201))));"Ni podatkov")
Vse skupaj je dejansko preprosto kot znana srbska nacionalna jed.
ponedeljek, 14. marec 2011
Odpiranje, zapiranje, rangi,...
Naslov je čuden, pa naj bo še vsebina. Sicer nič posebnega, mi je pa vzelo nekaj uric prijetnega dela.
Začetna želja je bila, da iz podatkov nekih sond (10 temperaturnih sond), naredimo poročilo, ki vsebuje minimalno, maksimalno in povprečno vrednost odčitka ter seveda nariše graf. Nič posebnega, lahko se naredi tudi "na roke". Toda življenje ni zanimivo, če ne malo kompliciramo.
V spodnjem nakladanju manjka samo še malo lepote. V izdelku je seveda še datoteka, z logotipom, opisom, gumbom za zagon...
No, da še malo opišem, kaj sploh je to. Ko zaženemo proceduro, se odpre okno za odpiranje datoteke (s podatki), odpremo datoteko in vpraša nas po območju, ki vsebuje potrebne podatke. Označimo, kliknemo OK in že sledi drugo odpiranje datoteke. Tokrat izberemo datoteko, ki vsebuje vzorec poročila in nekaj malega funkcij (min, max, average, if...malce, nam popravi izgled). V to datoteko se kopirajo podatki, ki smo jih izbrali v prejšnji datoteki. Nato procedura še nariše graf, nas vpraša kam želimo shraniti novo poročilo ter zapre datoteko s podatki in datoteko z vzorčnim poročilom.
Sub vnos()
Dim sPorocilo As String
Dim sPodatki As String
Dim wbPodatki As Variant
'odpremo datoteko s podatki
sPodatki = Application.GetOpenFilename(fileFilter:="Excel FIles (*.xls), *.xls", _
Title:="Prosim izberi datoteko s podatki")
If sPodatki = "False" Then Exit Sub
Workbooks.Open Filename:=sPodatki
wbPodatki = Application.ActiveWorkbook.Name
'V datoteki s podatki iz termometrov izberem obseg podatkov: od ure do zadnjega temperaturnega senzorja 'oz po želji
Dim rRange As Range
On Error Resume Next
Application.DisplayAlerts = False
Set rRange = Application.InputBox(Prompt:="Prosim izberi obseg vhodnih podatkov", _
Title:="Določi obseg", Type:=8)
On Error GoTo 0
Application.DisplayAlerts = True
If rRange Is Nothing Then
Exit Sub
Else
'podatke kopiramo
rRange.Copy
End If
'Odpiranje izbrane xls datoteke z vzorcem porocila
sPorocilo = Application.GetOpenFilename(fileFilter:="Excel Files (*.xls), *.xls", _
Title:="Prosim izberi datoteko z vzorcem poročila")
If sPorocilo = "False" Then Exit Sub
Workbooks.Open Filename:=sPorocilo
'aktiviramo delovni zvezek in nato delovni list ter skočimo v celico C30
ActiveWorkbook.Sheets("podatki").Activate
ActiveSheet.Cells(30, 3).Activate
'prilepimo podatke
ActiveCell.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'pobrišemo odložišče
Application.CutCopyMode = False
'narišemo graf
Dim povp As Range
Dim ura As Range
Dim vrstica As Integer
Dim vrs As String
Dim vrsx As String
ActiveWorkbook.Sheets("podatki").Activate
vrstica = WorksheetFunction.Count(Range("D30", "D25000")) + 29
vrs = "N" & vrstica
vrsx = "O" & vrstica
Set povp = Range("N30", vrs)
Set ura = Range("O30", vrsx)
ActiveWorkbook.Sheets("podatki").Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlLine
'seveda bo grafikon poimenovan grafikon in bo na svojem listu
ActiveChart.Location Where:=xlLocationAsNewSheet, Name:="Grafikon"
ActiveWorkbook.Charts("Grafikon").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(2).Name = "='podatki'!$N$29"
ActiveChart.SeriesCollection(2).Values = povp
ActiveChart.SeriesCollection(2).XValues = ura
ActiveChart.SeriesCollection(1).Delete
'in shranimo datoteko
fileSaveName = Application.GetSaveAsFilename( _
fileFilter:="Excel Files (*.xls), *.xls")
If fileSaveName = False Then
Exit Sub
End If
' Shrani datoteko v format xls
ActiveWorkbook.SaveAs Filename:= _
fileSaveName, FileFormat:=xlExcel8, _
CreateBackup:=False
'lepo je, če uporabniku kaj povemo
file_name_saved = ActiveWorkbook.FullName
MsgBox "Datototeka je shranjena: " & vbCr & vbCr & file_name_saved
'zapremo datoteko z vzorčnim poročilom in s podatki
ActiveWorkbook.Close
Workbooks(wbPodatki).Close
End Sub
Začetna želja je bila, da iz podatkov nekih sond (10 temperaturnih sond), naredimo poročilo, ki vsebuje minimalno, maksimalno in povprečno vrednost odčitka ter seveda nariše graf. Nič posebnega, lahko se naredi tudi "na roke". Toda življenje ni zanimivo, če ne malo kompliciramo.
V spodnjem nakladanju manjka samo še malo lepote. V izdelku je seveda še datoteka, z logotipom, opisom, gumbom za zagon...
No, da še malo opišem, kaj sploh je to. Ko zaženemo proceduro, se odpre okno za odpiranje datoteke (s podatki), odpremo datoteko in vpraša nas po območju, ki vsebuje potrebne podatke. Označimo, kliknemo OK in že sledi drugo odpiranje datoteke. Tokrat izberemo datoteko, ki vsebuje vzorec poročila in nekaj malega funkcij (min, max, average, if...malce, nam popravi izgled). V to datoteko se kopirajo podatki, ki smo jih izbrali v prejšnji datoteki. Nato procedura še nariše graf, nas vpraša kam želimo shraniti novo poročilo ter zapre datoteko s podatki in datoteko z vzorčnim poročilom.
Sub vnos()
Dim sPorocilo As String
Dim sPodatki As String
Dim wbPodatki As Variant
'odpremo datoteko s podatki
sPodatki = Application.GetOpenFilename(fileFilter:="Excel FIles (*.xls), *.xls", _
Title:="Prosim izberi datoteko s podatki")
If sPodatki = "False" Then Exit Sub
Workbooks.Open Filename:=sPodatki
wbPodatki = Application.ActiveWorkbook.Name
'V datoteki s podatki iz termometrov izberem obseg podatkov: od ure do zadnjega temperaturnega senzorja 'oz po želji
Dim rRange As Range
On Error Resume Next
Application.DisplayAlerts = False
Set rRange = Application.InputBox(Prompt:="Prosim izberi obseg vhodnih podatkov", _
Title:="Določi obseg", Type:=8)
On Error GoTo 0
Application.DisplayAlerts = True
If rRange Is Nothing Then
Exit Sub
Else
'podatke kopiramo
rRange.Copy
End If
'Odpiranje izbrane xls datoteke z vzorcem porocila
sPorocilo = Application.GetOpenFilename(fileFilter:="Excel Files (*.xls), *.xls", _
Title:="Prosim izberi datoteko z vzorcem poročila")
If sPorocilo = "False" Then Exit Sub
Workbooks.Open Filename:=sPorocilo
'aktiviramo delovni zvezek in nato delovni list ter skočimo v celico C30
ActiveWorkbook.Sheets("podatki").Activate
ActiveSheet.Cells(30, 3).Activate
'prilepimo podatke
ActiveCell.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'pobrišemo odložišče
Application.CutCopyMode = False
'narišemo graf
Dim povp As Range
Dim ura As Range
Dim vrstica As Integer
Dim vrs As String
Dim vrsx As String
ActiveWorkbook.Sheets("podatki").Activate
vrstica = WorksheetFunction.Count(Range("D30", "D25000")) + 29
vrs = "N" & vrstica
vrsx = "O" & vrstica
Set povp = Range("N30", vrs)
Set ura = Range("O30", vrsx)
ActiveWorkbook.Sheets("podatki").Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlLine
'seveda bo grafikon poimenovan grafikon in bo na svojem listu
ActiveChart.Location Where:=xlLocationAsNewSheet, Name:="Grafikon"
ActiveWorkbook.Charts("Grafikon").Activate
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(2).Name = "='podatki'!$N$29"
ActiveChart.SeriesCollection(2).Values = povp
ActiveChart.SeriesCollection(2).XValues = ura
ActiveChart.SeriesCollection(1).Delete
'in shranimo datoteko
fileSaveName = Application.GetSaveAsFilename( _
fileFilter:="Excel Files (*.xls), *.xls")
If fileSaveName = False Then
Exit Sub
End If
' Shrani datoteko v format xls
ActiveWorkbook.SaveAs Filename:= _
fileSaveName, FileFormat:=xlExcel8, _
CreateBackup:=False
'lepo je, če uporabniku kaj povemo
file_name_saved = ActiveWorkbook.FullName
MsgBox "Datototeka je shranjena: " & vbCr & vbCr & file_name_saved
'zapremo datoteko z vzorčnim poročilom in s podatki
ActiveWorkbook.Close
Workbooks(wbPodatki).Close
End Sub
četrtek, 10. marec 2011
Urejanje podatkov in zapolnitev celic
Danes sem bil soočen z zelo zanimivim izzivom. Kolega je potreboval malce statistično obdelane podatke.
Podatki obsegajo pojavljanje tornadov za mesece april, maj in junij, za tri zvezne države in še zanimivost, zbrani so za obdobje 1970 - 2010. Vsaka država je urejena na svojem listu, stolpci pa si sledijo tako: dan v mesecu, april, maj, junij, dan v mesecu, april, maj, junij, dan v mesecu,...
Najprej sem neobdelane podatke skopiral v nov zvezek in pobrisal podatke, ki me niso zanimali oziroma so me motili.
Sub brisanje()
Dim a As Integer
Dim i As Integer
'od zadnjega stolpca pobrišemo vsak 4. stolpec
For i = 1 To 40
a = 165 - (4 * i)
ActiveWorkbook.Sheets("List1").Select
ActiveSheet.Cells(1, a).EntireColumn.Delete
Next
End Sub
Nato sem skopiral podatke iz večih stolpcev v en sam stolpec:
Sub kopiranje()
Dim i As Integer
Dim a As Integer
For i = 1 To 41
a = i * 3
'izberemo prvi stolpec z uporabnimi podatki in jih kopiramo
ActiveWorkbook.Sheets("List1").Select
Range(Cells(3, a), Cells(32, a)).Select
Selection.Copy
'prilepimo jo na nov delovni list
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 - 90), 2).Select
ActiveSheet.Paste
'spet gremo na prvi delovni list in izberemo drugi stolpec in ga kopiramo
ActiveWorkbook.Sheets("List1").Select
Range(Cells(3, a + 1), Cells(33, a + 1)).Select
Selection.Copy
'prilepomo ga na koncu prvega kopiranega stolpca
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 + 30 - 90), 2).Select
ActiveSheet.Paste
ActiveWorkbook.Sheets("List1").Select
Range(Cells(3, a + 2), Cells(32, a + 2)).Select
Selection.Copy
'junij
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 + 61 - 90), 2).Select
ActiveSheet.Paste
'to naredimo za i * 41 stolpcev
Next
End Sub
Seveda moramo podatkom pripisati še datum. Vmes so seveda tudi prestopna leta, zato ne moremo direktno uporabit funkcije =A1+365 ;)
Lahko pa naredimo tako:
Sub datumi()
Dim i As Integer
For i = 1 To 41
'izberemo prvo celico na listu 2 in vanjo vpišemo 1.4. (na angleški način)
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 - 90), 1).Select
ActiveCell = "4/1/" & 1969 + i
'nato zapolnimo vseh 90 zaporednih dni in v drugem krogu spet vpišemo 1.4. in prištejemo i-to leto
Selection.AutoFill Destination:=Range(Cells((i * 91 - 90), 1), Cells((i * 91), 1))
Next
End Sub
To je nekako to. Za napake pa ne odgovarjam, zato uporabljajte varnostne kopije podatkov.
Podatki obsegajo pojavljanje tornadov za mesece april, maj in junij, za tri zvezne države in še zanimivost, zbrani so za obdobje 1970 - 2010. Vsaka država je urejena na svojem listu, stolpci pa si sledijo tako: dan v mesecu, april, maj, junij, dan v mesecu, april, maj, junij, dan v mesecu,...
Najprej sem neobdelane podatke skopiral v nov zvezek in pobrisal podatke, ki me niso zanimali oziroma so me motili.
Sub brisanje()
Dim a As Integer
Dim i As Integer
'od zadnjega stolpca pobrišemo vsak 4. stolpec
For i = 1 To 40
a = 165 - (4 * i)
ActiveWorkbook.Sheets("List1").Select
ActiveSheet.Cells(1, a).EntireColumn.Delete
Next
End Sub
Nato sem skopiral podatke iz večih stolpcev v en sam stolpec:
Sub kopiranje()
Dim i As Integer
Dim a As Integer
For i = 1 To 41
a = i * 3
'izberemo prvi stolpec z uporabnimi podatki in jih kopiramo
ActiveWorkbook.Sheets("List1").Select
Range(Cells(3, a), Cells(32, a)).Select
Selection.Copy
'prilepimo jo na nov delovni list
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 - 90), 2).Select
ActiveSheet.Paste
'spet gremo na prvi delovni list in izberemo drugi stolpec in ga kopiramo
ActiveWorkbook.Sheets("List1").Select
Range(Cells(3, a + 1), Cells(33, a + 1)).Select
Selection.Copy
'prilepomo ga na koncu prvega kopiranega stolpca
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 + 30 - 90), 2).Select
ActiveSheet.Paste
ActiveWorkbook.Sheets("List1").Select
Range(Cells(3, a + 2), Cells(32, a + 2)).Select
Selection.Copy
'junij
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 + 61 - 90), 2).Select
ActiveSheet.Paste
'to naredimo za i * 41 stolpcev
Next
End Sub
Seveda moramo podatkom pripisati še datum. Vmes so seveda tudi prestopna leta, zato ne moremo direktno uporabit funkcije =A1+365 ;)
Lahko pa naredimo tako:
Sub datumi()
Dim i As Integer
For i = 1 To 41
'izberemo prvo celico na listu 2 in vanjo vpišemo 1.4. (na angleški način)
ActiveWorkbook.Sheets("List2").Select
ActiveSheet.Cells((i * 91 - 90), 1).Select
ActiveCell = "4/1/" & 1969 + i
'nato zapolnimo vseh 90 zaporednih dni in v drugem krogu spet vpišemo 1.4. in prištejemo i-to leto
Selection.AutoFill Destination:=Range(Cells((i * 91 - 90), 1), Cells((i * 91), 1))
Next
End Sub
To je nekako to. Za napake pa ne odgovarjam, zato uporabljajte varnostne kopije podatkov.
petek, 4. marec 2011
Zapolnjevanje praznih celic
Velikokrat kopiramo razne tabele iz Worda (besedilni urejevalnik) v Excel, pri tem pa pride do pojava praznih celic. Tega niti ne zaznamo kot težave, dokler nismo prisiljeni teh podatkov obdelati za nadaljne analize. Sam sem imel tako težavo, ker so v "stolpcu B" (naziv naselja) bili podatki, ki sem jih potreboval za nadaljno obdelavo. Zato sem si malo pomagal z VBA
Sub zapolni()
'najde prvo prazno celico in vanjo prepiše vrednost in zadnje polne celice
Dim i As Integer
'Nastavljeno je na korak 20 vrstic, ker se to lepo vidi na eni velikosti zaslona
For i = RowCount To 20 Step 1
'Range je določen za maksimalno velikost. ni pa potrebno,ker se sam odločiš kdaj neha delat
'Trenutno je izbran stolpec B
Range("B65536").End(xlUp).Select
Range("B1").End(xlDown).Offset(1, 0).Select
ActiveCell.Offset(-1, 0).Copy
ActiveCell.Offset(0, 0).PasteSpecial xlPasteAllExceptBorders
Next
End Sub
Sub zapolni()
'najde prvo prazno celico in vanjo prepiše vrednost in zadnje polne celice
Dim i As Integer
'Nastavljeno je na korak 20 vrstic, ker se to lepo vidi na eni velikosti zaslona
For i = RowCount To 20 Step 1
'Range je določen za maksimalno velikost. ni pa potrebno,ker se sam odločiš kdaj neha delat
'Trenutno je izbran stolpec B
Range("B65536").End(xlUp).Select
Range("B1").End(xlDown).Offset(1, 0).Select
ActiveCell.Offset(-1, 0).Copy
ActiveCell.Offset(0, 0).PasteSpecial xlPasteAllExceptBorders
Next
End Sub
Naročite se na:
Objave (Atom)


