Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1508to1512
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Auffüllen von Leerstellen

Auffüllen von Leerstellen
28.08.2016 15:23:23
Leerstellen
Moin,
mein Problem:
Ich habe sehr lange Datenreihen, wo mir manchmal Werte fehlen.
Diese Leerstellen möchte ich gerne auffüllen.
Datei:
https://www.herber.de/bbs/user/107863.xlsx
Die leeren Zellen sollen dabei nicht einfach den alten Wert haben sondern insgesamt einen gleichmäßigen Anstieg/bzw. Abfall zum nächsten vorhandenen Wert bilden.
Ich denke, es muss per Vergleich und Index möglich sein, das zu bewerkstelligen.
Die Fehlstellen haben unterschiedliche Längen (die längste ist aber kleiner als 200 Zeilen). In der Originaldatei handelt es sich um mehr als 800.000 Zeilen, weswegen eine Formel schön wäre, die nicht viel Rechenleistung zieht.

26
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Auffüllen von Leerstellen
28.08.2016 16:12:25
Leerstellen
Hi,
wenn Du "keine Rechenleistung" beanspruchen willst, nimmst Du am besten ein VBA-Skript, das die Arbeit genau dann EINMAL erledigt, wenn sie benötigt wird.
Ist das zielführend?
Gruß,
Michael
AW: Auffüllen von Leerstellen
28.08.2016 16:55:35
Leerstellen
Hallo,
der folgen Code schreibt die interpolierten Werte in Spalte "D" und müßte nach der Kontrolle zurück in Spalte "A" kopiert werden. Es werden nur minimale Ressourcen benötigt.

Sub Rene()
Dim ar As Range
Dim Anfa As Single, Ende As Single
With Sheets(1).UsedRange.Columns(1).SpecialCells(4)
For Each ar In .Areas
Anfa = Range(Split(ar.Address, ":")(0)).Offset(-1).Value
Ende = Range(Split(ar.Address, ":")(1)).Offset(1).Value
ar.Item(1).Offset(0, 3) = Anfa + (Ende - Anfa) / (ar.Count + 1)
For i = 2 To ar.Count
ar.Item(i).Offset(0, 3) = ar.Item(i - 1).Offset(0, 3).Value + (Ende - Anfa) / (ar. _
Count + 1)
Next i
Next
End With
End Sub
mfg
Anzeige
AW: Auffüllen von Leerstellen
28.08.2016 17:44:23
Leerstellen
Herzlichen Dank für diese anwenderfreundliche Version.
Die VBA-Inhalte gehen weit über mein bisheriges Wissen hinaus :D
Ich konnte selber die Quell und Zielspalte ändern.
Und tatsächlich quasi null CPU-Power benötigt.
Mal gucken, was in meiner Originaldatei los ist.
AW: Auffüllen von Leerstellen
28.08.2016 17:59:04
Leerstellen
Ich bin noch über ein Problem gestolpert:
Kann man den Code so anpassen, dass das auch bei einer Lücke von nur einer Zeile klappt?
Der bleibt sonst immer stehen an dieser Stelle und ich muss die manuell ausbessern.
Thx
AW: Auffüllen von Leerstellen
28.08.2016 18:03:12
Leerstellen
Hallo,
ungeprüft:

Sub Rene()
Dim ar As Range
Dim Anfa As Single, Ende As Single
With Sheets(1).UsedRange.Columns(1).SpecialCells(4)
For Each ar In .Areas
Anfa = Range(Split(ar.Address, ":")(0)).Offset(-1).Value
Ende = Range(Split(ar.Address, ":")(1)).Offset(1).Value
ar.Item(1).Offset(0, 3) = Anfa + (Ende - Anfa) / (ar.Count + 1)
if ar.count > 1 then
For i = 2 To ar.Count
ar.Item(i).Offset(0, 3) = ar.Item(i - 1).Offset(0, 3).Value + (Ende - Anfa) / (ar.  _
_
Count + 1)
Next i
end if
Next
End With
End Sub

Anzeige
AW: Auffüllen von Leerstellen
28.08.2016 18:05:20
Leerstellen
Hallo,
achso, da der Code auf die Leerzellen in Spalte "A" abstellt, sollten diese Zellen erst beschrieben werden, wenn die Schleife durchgelaufen ist.
mfg
AW: Auffüllen von Leerstellen
28.08.2016 21:07:20
Leerstellen
Ne, leider klappt´s noch nicht.
Bei diesem Part bleibt das Sub stehen:
Ende = Range(Split(ar.Address, ":")(1)).Offset(1).Value
Anbei nochmal ne Beispieldatei mit dem Makro drin.
https://www.herber.de/bbs/user/107865.xlsm
(Ich habe beim Teil hier unten die Absätze und Unterstriche entfernt, weil das rot angezeigt _ wurde:

(ar.  _
_
Count + 1)

Anzeige
AW: getestet Lösung (final)
28.08.2016 21:30:49
Fennek
Hallo,
es war doc nicht so einfach, eine Fallunterscheidung war notwendig:

Sub Rene()
Dim ar As Range
Dim Anfa As Single, Ende As Single
With Sheets(1).UsedRange.Columns(1).SpecialCells(4)
For Each ar In .Areas
Select Case ar.Count
Case Is = 1
Anfa = ar.Offset(-1).Value
Ende = ar.Offset(1).Value
ar.Value = Anfa + (Ende - Anfa) / 2
Case Is > 1
Anfa = Range(Split(ar.Address, ":")(0)).Offset(-1).Value
Ende = Range(Split(ar.Address, ":")(1)).Offset(1).Value
ar.Item(1).Offset(0, 0) = Anfa + (Ende - Anfa) / (ar.Count + 1)
For i = 2 To ar.Count
ar.Item(i).Offset(0, 0) = ar.Item(i - 1).Offset(0, 0).Value + (Ende - Anfa) / (ar. _
Count + 1)
Next i
End Select
Next
End With
End Sub
mfg
Anzeige
AW: getestet Lösung (final)
28.08.2016 21:32:42
René
Danke für deine Zeit.
Werde ich nachher mal probieren.
AW: getestet Lösung (final)
28.08.2016 21:42:08
René
Wie nice.
Man konnte die ja direkt auffüllen lassen.
Das spart mir nachher viel Verschiebearbeit :D
D.h. jetzt muss ich nur noch die Spalten als double dimmen und dann kann ich ja für eine x-beliebige Spalte ausführen.
Sehr tolle Lösung
AW: getestet Lösung (final)
28.08.2016 21:54:03
snb
Zum reduzieren der Worksheet Interaktion:
Sub M_snb()
sn = UsedRange.Columns(1)
For Each ar In Columns(1).SpecialCells(4).Areas
y = (ar.Cells(1).Offset(ar.Count).Value - ar.Cells(1).Offset(-1).Value) / (ar.Count + 1)
For j = ar.Cells(1).Row To ar.Cells(1).Row + ar.Count
sn(j, 1) = sn(j - 1, 1) + y
Next
Next
UsedRange.Columns(1).Offset(, 5) = sn
End Sub

Anzeige
AW: Grüße an die nächste Dimension
29.08.2016 08:03:02
Fennek
Hallo Rene,
(falls nötig: usedrange -> activesheet.usedrange)
Um die Zeit des Laufzeit zu bestimmen, füge am Anfang ein
Start = timer
und am Ende
msgbox timer - start
Vermutung: von den 800.000 Zeilen müssen relativ wenig interpoliert werden.

Sub Rene()
Dim ar As Range
Dim c As Range
For Each ar In ActiveSheet.UsedRange.Columns(1).SpecialCells(4).Areas
y = (ar.Cells(1).Offset(ar.Count).Value - ar.Cells(1).Offset(-1).Value) / (ar.Count + 1)
For Each c In ar
c = c.Offset(-1) + y
Next c
Next ar
End Sub
mfg
PS: Vermutung: Laufzeit unter 5 Sekunden
Anzeige
AW: Grüße an die nächste Dimension
29.08.2016 08:41:43
René
Annahme korrekt.
Laufzeit unter 5 Sekunden.
Mit so einer schnellen Lösung hätte ich nicht gerechnet.
Und ja, die Leerstellen machen weniger als 2% aus.
AW: Grüße an die nächste Dimension
29.08.2016 12:08:32
snb
Und dann ist meiner Vorschlag noch immer die schnellste: weniger als 1 sek.
liefert aber "Object erforderlich"...owT-Gruß
29.08.2016 12:18:30
robert
AW: getestet Lösung (final)
29.08.2016 12:19:39
snb
Neue Version:
Sub M_snb()
sn = UsedRange.Columns(1)
For Each ar In Columns(1).SpecialCells(4).Areas
x = ar.Cells(1).Row
z = ar.Count
y = (sn(x + z, 1) - sn(x - 1, 1)) / (z + 1)
For j = x To x + z
sn(j, 1) = sn(j - 1, 1) + y
Next
Next
UsedRange.Columns(1).Offset(, 5) = sn
End Sub

AW: getestet ?
29.08.2016 12:39:06
robert
sn = UsedRange.Columns(1) Fehler:Objekt erforderlich
Gruß
robert
Anzeige
AW: getestet ?
29.08.2016 13:24:07
snb
Im Codemodule des Werkblattes setzen
ok, aber nun Laufzeitfehler 9 ..... Gruß
29.08.2016 13:48:14
robert
Jetzt OK..
29.08.2016 18:55:24
robert
Hi,
möglicherweise war die Tabelle1 korrupt ;-)
läuft jetzt tadellos-Danke und Gruß
robert
AW: Jetzt OK..
29.08.2016 21:16:48
snb
Bist du Robert oder René, oder ....
AW: Jetzt OK..
29.08.2016 21:20:47
René
Ich bin René und mein Problem wurde schon durch fennek's Lösung behoben.
Zur Info:
Hatte noch eine andere große Datei auf Lager mit mehr fehlStellen als Werten.
Berechnung dauerte statt unter 5 Sekunden mehr als 10 Minuten.
Die anderen Beiträge stammen nicht von mir :-D
Anzeige
AW: Speed-Test:
29.08.2016 22:29:17
Fennek
Hallo,
noch eine kleine Übung nach einer halben Flasche Sekt:
Welcher code ist schneller?
Testumgebung: 2% der Werte fehlen

Sub Test_Umgebung()
dif = 1400
With Range("A1:A60000")
.Formula = "=row()"
.Value = .Value
For i = 1 To 8
For y = 1 To i
Z = Z + dif
Cells(Z, "A").Resize(2 ^ (9 - i)).Clear
Next y
Next i
End With
End Sub
Die letzten Codes von snb und Fennek

Sub linere_Interpolation()
Start = Timer
'in Spalte A stehen Werte, einige sind leer
Dim ar As Range
Dim c As Range
For Each ar In ActiveSheet.UsedRange.Columns(1).SpecialCells(4).Areas
y = (ar.Cells(1).Offset(ar.Count).Value - ar.Cells(1).Offset(-1).Value) / (ar.Count + 1)
For Each c In ar
c = c.Offset(-1) + y
Next c
Next ar
MsgBox Timer - Start
End Sub
Sub M_snb()
Start = Timer
sn = ActiveSheet.UsedRange.Columns(1)
For Each ar In Columns(1).SpecialCells(4).Areas
y = (ar.Cells(1).Offset(ar.Count).Value - ar.Cells(1).Offset(-1).Value) / (ar.Count + 1)
For j = ar.Cells(1).Row To ar.Cells(1).Row + ar.Count
sn(j, 1) = sn(j - 1, 1) + y
Next
Next
ActiveSheet.UsedRange.Columns(1).Offset(, 5) = sn
MsgBox Timer - Start
End Sub
Die absoluten Werte sind nicht relevant, da die benutzte Hard etwas "outdated" war:
snb: 0,28 Sekunden
Fen: 0,09 Sekunden
mfg
Anzeige
AW: Speed-Test:
29.08.2016 22:33:27
René
Dann habe ich ja alles richtig gemacht, mit meiner Wahl:-P
Sonst säße ich heute immer noch vorm Rechner und hätte das Makro angefeuert...
AW: Speed-Test:
01.09.2016 12:49:24
Michael
Hi Fenneck,
ich habe mich noch an einer "reinen" Array-Lösung versucht, aber die bringt einfach nicht die Performance.
Es scheint so ähnlich zu sein wie mit einem Dictionary, das eben auch rasend schnell ist, weil eine "datenbankmäßige", "indizierte" Logik dahintersteckt.
Excel weiß intern offensichtlich "automatisch", wo Anfang und Ende beschriebener bzw. leerer Bereiche sind, das ist mit einem sequentiellen Algo nicht zu toppen.
Vielen Dank & schöne Grüße,
Michael

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige