141 lines
5.5 KiB
Mathematica
141 lines
5.5 KiB
Mathematica
// Power Query from: Railfan Stuff.xlsx
|
|
// Pathname: c:\Users\tm24f\OneDrive\Documents2\Railfan Stuff\Railfan Stuff.xlsx
|
|
// Extracted: 2025-10-06T22:57:24.500Z
|
|
|
|
section Section1;
|
|
|
|
shared CSX_roster = let
|
|
// Load + basic shaping
|
|
Source = Csv.Document(
|
|
File.Contents("X:\railfan\CSX_roster.csv"),
|
|
[Delimiter=",", Columns=6, Encoding=1252, QuoteStyle=QuoteStyle.None]
|
|
),
|
|
PromoteHeaders = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
|
|
ChangeType = Table.TransformColumnTypes(
|
|
PromoteHeaders,
|
|
{{"Unit No", type text}, {"Notes", type text}, {"Model", type text}, {"Serial", type text}, {"No Pictures", Int64.Type}, {"Col", Int64.Type}}
|
|
),
|
|
RemovedCols = Table.RemoveColumns(ChangeType, {"No Pictures", "Col"}),
|
|
|
|
// Helper: case-insensitive "does txt contain any of the terms?"
|
|
HasAny = (txt as nullable text, terms as list) as logical =>
|
|
let
|
|
s = if txt = null then "" else txt,
|
|
hit = List.AnyTrue(List.Transform(terms, (t as text) => Text.Contains(s, t, Comparer.OrdinalIgnoreCase)))
|
|
in
|
|
hit,
|
|
|
|
// Blocklists per column (easy to add/remove items)
|
|
NotesBlock = {
|
|
"sold", "retired", "rebuilt to", "scrapped", "rebuilt as",
|
|
"rebult to", "sold to", "destroyed", "re#", "renumbered",
|
|
"duplicate"
|
|
},
|
|
SerialBlock = { "duplicate" },
|
|
|
|
// Single combined filter step
|
|
Filtered =
|
|
Table.SelectRows(
|
|
RemovedCols,
|
|
(r) =>
|
|
// Keep row only if:
|
|
// 1) Unit No does NOT contain "UNKNOWN"
|
|
(not Text.Contains(if r[Unit No] = null then "" else r[Unit No], "UNKNOWN", Comparer.OrdinalIgnoreCase))
|
|
// 2) Notes does NOT contain any blocked term
|
|
and (not HasAny(r[Notes], NotesBlock))
|
|
// 3) Serial does NOT contain any blocked term
|
|
and (not HasAny(r[Serial], SerialBlock))
|
|
)
|
|
in
|
|
Filtered
|
|
;
|
|
|
|
shared AMTK_roster = let
|
|
// Load + basic shaping
|
|
Source = Csv.Document(
|
|
File.Contents("X:\railfan\AMTK_roster.csv"),
|
|
[Delimiter=",", Columns=6, Encoding=1252, QuoteStyle=QuoteStyle.None]
|
|
),
|
|
PromoteHeaders = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
|
|
ChangeType = Table.TransformColumnTypes(
|
|
PromoteHeaders,
|
|
{{"Unit No", type text}, {"Notes", type text}, {"Model", type text}, {"Serial", type text}, {"No Pictures", Int64.Type}, {"Col", Int64.Type}}
|
|
),
|
|
RemovedCols = Table.RemoveColumns(ChangeType, {"No Pictures", "Col"}),
|
|
|
|
// Helper: case-insensitive "does txt contain any of the terms?"
|
|
HasAny = (txt as nullable text, terms as list) as logical =>
|
|
let
|
|
s = if txt = null then "" else txt,
|
|
hit = List.AnyTrue(List.Transform(terms, (t as text) => Text.Contains(s, t, Comparer.OrdinalIgnoreCase)))
|
|
in
|
|
hit,
|
|
|
|
// Blocklists per column (easy to add/remove items)
|
|
NotesBlock = {
|
|
"sold", "retired", "rebuilt to", "scrapped", "rebuilt as",
|
|
"rebult to", "sold to", "destroyed", "re#", "renumbered",
|
|
"duplicate"
|
|
},
|
|
SerialBlock = { "duplicate" },
|
|
|
|
// Single combined filter step
|
|
Filtered =
|
|
Table.SelectRows(
|
|
RemovedCols,
|
|
(r) =>
|
|
// Keep row only if:
|
|
// 1) Unit No does NOT contain "UNKNOWN"
|
|
(not Text.Contains(if r[Unit No] = null then "" else r[Unit No], "UNKNOWN", Comparer.OrdinalIgnoreCase))
|
|
// 2) Notes does NOT contain any blocked term
|
|
and (not HasAny(r[Notes], NotesBlock))
|
|
// 3) Serial does NOT contain any blocked term
|
|
and (not HasAny(r[Serial], SerialBlock))
|
|
)
|
|
in
|
|
Filtered;
|
|
|
|
shared NS_roster = let
|
|
// Load + basic shaping
|
|
Source = Csv.Document(
|
|
File.Contents("X:\railfan\NS_roster.csv"),
|
|
[Delimiter=",", Columns=6, Encoding=1252, QuoteStyle=QuoteStyle.None]
|
|
),
|
|
PromoteHeaders = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
|
|
ChangeType = Table.TransformColumnTypes(
|
|
PromoteHeaders,
|
|
{{"Unit No", type text}, {"Notes", type text}, {"Model", type text}, {"Serial", type text}, {"No Pictures", Int64.Type}, {"Col", Int64.Type}}
|
|
),
|
|
RemovedCols = Table.RemoveColumns(ChangeType, {"No Pictures", "Col"}),
|
|
|
|
// Helper: case-insensitive "does txt contain any of the terms?"
|
|
HasAny = (txt as nullable text, terms as list) as logical =>
|
|
let
|
|
s = if txt = null then "" else txt,
|
|
hit = List.AnyTrue(List.Transform(terms, (t as text) => Text.Contains(s, t, Comparer.OrdinalIgnoreCase)))
|
|
in
|
|
hit,
|
|
|
|
// Blocklists per column (easy to add/remove items)
|
|
NotesBlock = {
|
|
"sold", "retired", "rebuilt to", "scrapped", "rebuilt as",
|
|
"rebult to", "sold to", "destroyed", "re#", "renumbered",
|
|
"duplicate"
|
|
},
|
|
SerialBlock = { "duplicate" },
|
|
|
|
// Single combined filter step
|
|
Filtered =
|
|
Table.SelectRows(
|
|
RemovedCols,
|
|
(r) =>
|
|
// Keep row only if:
|
|
// 1) Unit No does NOT contain "UNKNOWN"
|
|
(not Text.Contains(if r[Unit No] = null then "" else r[Unit No], "UNKNOWN", Comparer.OrdinalIgnoreCase))
|
|
// 2) Notes does NOT contain any blocked term
|
|
and (not HasAny(r[Notes], NotesBlock))
|
|
// 3) Serial does NOT contain any blocked term
|
|
and (not HasAny(r[Serial], SerialBlock))
|
|
)
|
|
in
|
|
Filtered; |