HERBERS Excel-Forum - das Archiv

Thema: gezippte CSV als Datenquelle

gezippte CSV als Datenquelle
Christian
Hallo,

ich hätte mal eine Frage an euch, ich nutze in einem M-Code die Zeile

=     A = Date.ToText(Date.From(DateTime.LocalNow()), "yyyy-MM-dd"),


Quelle = Csv.Document(
File.Contents("C:\Users\chris\Downloads\zHV_aktuell_csv." & A & "\zHV_aktuell_csv." & A & ".csv"),
[Delimiter=";", Columns=17, Encoding=65001, QuoteStyle=QuoteStyle.None]
),


als Quelle, nachdem ich den Ordner zHV_aktuell_csv.2025-08-25.zip entpackt habe.

Gibt es da auch einen anderen Weg, der auf das ZIP Archiv zugreifen kann, ich mir also das entpacken sparen kann?

Danke
Christian
AW: gezippte CSV als Datenquelle
Marc
Inhalt ZIP DAtei auflisten



Sub ListZipContents()
Dim oShell As Object
Dim oZip As Object
Dim oItem As Object

Set oShell = CreateObject("Shell.Application")
Set oZip = oShell.Namespace("C:\Test\Beispiel.zip")

If Not oZip Is Nothing Then
For Each oItem In oZip.Items
Debug.Print oItem.Name, oItem.Size
Next
Else
MsgBox "ZIP-Datei nicht gefunden!"
End If
End Sub



Dateien aus Zip auspacken (danach kannst du auf das einzelne File auch zugreifen:



Sub ExtractFromZip()
Dim oShell As Object
Dim oZip As Object
Dim oTarget As Object

Set oShell = CreateObject("Shell.Application")
Set oZip = oShell.Namespace("C:\Test\Beispiel.zip")
Set oTarget = oShell.Namespace("C:\Test\Entpackt")

If Not oZip Is Nothing Then
oTarget.CopyHere oZip.Items, 16 '16 = ohne Fortschrittsdialog
MsgBox "Fertig!"
End If
End Sub



Du kannst auch über eine Shell Vorgabe drauf zu greifen (Winrar, Winzip)



Shell "7z x C:\Test\Beispiel.zip -oC:\Test\Entpackt -y", vbHide



entpacken musst du immer
AW: gezippte CSV als Datenquelle
Yal
Moin,

interessehalber habe ich ganz naiv nach "Power Query Zip" ge-Duckduckgo-et.

Der Beitrag
https://community.fabric.microsoft.com/t5/Power-BI-Community-Blog/PowerQuery-Decompress-zip-Files/ba-p/1326035
scheint der richtige Treffer zu sein.

let

Quelle = Decompress(File.Contents("C:\temp\H_Forum\meinZip.zip"))
in
Quelle
gilt als Grundgerüst. Dabei ist "Decompress" eine Functionsabfrage, die aus dem Code im Beitrag besteht. Auch unter
https://github.com/Michael19842/PowerBiFunctions/blob/main/ZipFile/Unzip.m
zu haben. (leere Abfrage starten, alles löschen, Code komplett hinein pasten und Abfrage dem Namen "Decompress" verpassen)
Danach die Dateien-Inhalt in üblicher Form extrahieren/behandeln.

VG
Yal
AW: gezippte CSV als Datenquelle
Christian
Hallo Yal,

danke für den Hinweis.

Gut zugegebenermaßen, ich habe ChatGPT zur Hilfe gezogen und damit folgendes gemacht:

die Funktion DecompressZip erstellt:

(ZIPFile) =>

let
Header = BinaryFormat.Record([
MiscHeader = BinaryFormat.Binary(14),
BinarySize = BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
FileSize = BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
FileNameLen= BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian),
ExtrasLen = BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian)
]),

HeaderChoice = BinaryFormat.Choice(
BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
each if _ <> 67324752
then BinaryFormat.Record([IsValid = false, Filename=null, Content=null])
else BinaryFormat.Choice(
BinaryFormat.Binary(26),
each BinaryFormat.Record([
IsValid = true,
Filename = BinaryFormat.Text(Header(_)[FileNameLen]),
Extras = BinaryFormat.Text(Header(_)[ExtrasLen]),
Content = BinaryFormat.Transform(
BinaryFormat.Binary(Header(_)[BinarySize]),
(x) => try Binary.Buffer(Binary.Decompress(x, Compression.Deflate)) otherwise null
)
]),
type binary
)
),

ZipFormat = BinaryFormat.List(HeaderChoice, each _[IsValid] = true),

Entries = List.Transform(
List.RemoveLastN( ZipFormat(ZIPFile), 1),
(e) => [FileName = e[Filename], Content = e[Content] ]
)
in
Table.FromRecords(Entries)


und meine Abfrage entsprechend angepasst:

let

// aktuelles Datum für Dateinamen
A = Date.ToText(Date.From(DateTime.LocalNow()), "yyyy-MM-dd"),

// ZIP-Datei-Pfad
PfadZip = "C:\Users\chris\Downloads\zHV_aktuell_csv." & A & ".zip",

// ZIP-Datei einlesen und entpacken
Quelle = File.Contents(PfadZip),
Entpackt = DecompressZip(Quelle),

// passende CSV aus dem ZIP auswählen
CSVFile = Table.SelectRows(Entpackt, each [FileName] = "zHV_aktuell_csv." & A & ".csv"),
Inhalt = CSVFile{0}[Content],

// CSV in Tabelle einlesen
QuelleCSV = Csv.Document(
Inhalt,
[Delimiter=";", Columns=17, Encoding=65001, QuoteStyle=QuoteStyle.None]
),

#"Header gesetzt" = Table.PromoteHeaders(QuelleCSV, [PromoteAllScalars=true]),

// unnötige Spalten entfernen
#"Spalten reduziert" = Table.RemoveColumns(#"Header gesetzt", {
"Type", "DHID", "Parent", "MunicipalityCode", "DistrictCode", "District",
"Description", "Authority", "DelfiName", "THID", "TariffProvider"
}),

// nur gültige Zeilen mit Municipality
#"Nur gültige Zeilen" = Table.SelectRows(#"Spalten reduziert", each [Municipality] <> "-"),

// Spaltentypen konvertieren
#"Typen konvertiert" = Table.TransformColumnTypes(#"Nur gültige Zeilen", {
{"SeqNo", Int64.Type}, {"Name", type text}, {"Latitude", type number},
{"Longitude", type number}, {"Municipality", type text},
{"LastOperationDate", type datetime}
}),

// LastOperationDate als Datum
#"LastOperationDate als Datum" = Table.TransformColumnTypes(#"Typen konvertiert", {
{"LastOperationDate", type date}
}),

// Referenzkoordinaten
latRef = 50.7624067,
lonRef = 6.9998638,

// Entfernung berechnen (Haversine)
MitEntfernung = Table.AddColumn(#"LastOperationDate als Datum", "Entfernung_km", each let
lat1 = latRef * Number.PI / 180,
lon1 = lonRef * Number.PI / 180,
lat2 = [Latitude] * Number.PI / 180,
lon2 = [Longitude] * Number.PI / 180,
dLat = lat2 - lat1,
dLon = lon2 - lon1,
a = Number.Power(Number.Sin(dLat / 2), 2) +
Number.Cos(lat1) * Number.Cos(lat2) * Number.Power(Number.Sin(dLon / 2), 2),
c = 2 * Number.Atan2(Number.Sqrt(a), Number.Sqrt(1 - a)),
r = 6371.0088,
dist = r * c
in
Number.Round(dist, 7)),

// Filter auf 80 km Umkreis
#"Gefiltert auf Umkreis" = Table.SelectRows(MitEntfernung, each [Entfernung_km] <= 80),

// Koordinaten-Spalte ergänzen
MitKoordinaten = Table.AddColumn(#"Gefiltert auf Umkreis", "Koordinaten", each
Number.ToText([Latitude], "0.000000", "en-US") & " " & Number.ToText([Longitude], "0.000000", "en-US"),
type text
),

// Endgültige Spaltenreihenfolge
Ergebnis = Table.ReorderColumns(MitKoordinaten, {
"SeqNo", "Name", "Latitude", "Longitude", "Koordinaten", "Municipality", "LastOperationDate", "Entfernung_km"
}),

// Sortierung nach Entfernung
Sortiert = Table.Sort(Ergebnis, {{"Entfernung_km", Order.Ascending}})
in
Sortiert


funktioniert einwandfrei. Vielen Dank
Christian
AW: gezippte CSV als Datenquelle
Yal
Nun, die Ähnlichkeit ist kaum zu übersehen. Da braucht man nicht lang um zu verstehen, wo ChatGPT sich um den Wissen "reicher" gemacht hat...

VG
Yal
Irrtum
Christian
ich hab von den Internetseiten Copy + Paste gemacht, dazu meinen Code und Chatgpt gesagt "mach mal".
AW: Irrtum
Yal
ach so... An dieser Möglichkeit hatte ich gar nicht gedacht.
Dann geht es auf deinem Verdienst, kreativ/konstruktiv mit ChatGPT umzugehen.

VG
Yal
AW: gezippte CSV als Datenquelle
Christian
Hallo Marc,

also du willst darauf hinaus, anstatt die ZIP händig zu entpacken und danach die Abfrage zu aktualisieren, VBA einsetzen, um die ZIP Datei zu entpacken. Da VBA ja auch die Abfrage aktualisieren kann, kann VBA ja dann auch beides in einem Abwasch machen.

Diese Alternative schaue ich mir auf jeden Fall mal an.

Danke
Christian
Testversuch
Christian
Ich habe es mit dem Code hier probiert: aber mir wird gesagt "Fehler: ZIP oder Zielordner konnte nicht geöffnet werden!" obwohl die Datei zHV_aktuell_csv.2025-08-25.zip in meinem Download Ordner existiert. chris ist auch der korrekte Nutername, ich hab auch den Pfad zu meinen Downloads nie geändert.



Option Explicit

Sub Entpacke_ZHV_und_Aktualisiere()
Dim sDatum As String
Dim sZipDatei As String
Dim sZielPfad As String
Dim oShell As Object
Dim oZip As Object
Dim oTarget As Object

' Aktuelles Datum im Format YYYY-MM-DD
sDatum = Format(Date, "yyyy-mm-dd")

' Pfade zusammenbauen
sZipDatei = "C:\Users\chris\Downloads\zHV_aktuell_csv." & sDatum & ".zip"
sZielPfad = "C:\Users\chris\Downloads\zHV_aktuell_csv." & sDatum

' Shell-Objekte setzen
Set oShell = CreateObject("Shell.Application")
Set oZip = oShell.Namespace(sZipDatei)
If Dir(sZielPfad, vbDirectory) = "" Then MkDir sZielPfad
Set oTarget = oShell.Namespace(sZielPfad)

' Entpacken falls ZIP ok ist
If Not oZip Is Nothing And Not oTarget Is Nothing Then
oTarget.CopyHere oZip.Items, 16 '16 = ohne Dialoge
Else
MsgBox "Fehler: ZIP oder Zielordner konnte nicht geöffnet werden!", vbCritical
Exit Sub
End If

' kurze Wartezeit für das Entpacken
Application.Wait (Now + TimeValue("0:00:05"))

' Abfrage(n) aktualisieren (bei dir nur zHV)
ThisWorkbook.RefreshAll

MsgBox "Fertig: " & vbCrLf & sZipDatei & vbCrLf & " entpackt nach " & sZielPfad & vbCrLf & "und Abfrage 'zHV' aktualisiert.", vbInformation
End Sub
AW: Testversuch
Marc




sZielPfad = "C:\Users\chris\Downloads\zHV_aktuell_csv." & sDatum


ist kein Pfad
das ist eine Datei ...

und ein Pfad muss immer auf \ enden..