Skip to content

Instantly share code, notes, and snippets.

View m-dekorte's full-sized avatar

Melissa de Korte m-dekorte

View GitHub Profile
@m-dekorte
m-dekorte / extractCharactersByCase.pq
Created April 20, 2025 12:32
extractCharactersByCase M function | Extract only letters of a specified case. Non‑letter characters (digits, punctuation, whitespace) are dropped.
let
extractCharactersByCase = (input as nullable text, optional caseType as text) as text =>
Text.Combine(
List.Select(
Text.ToList(input ?? ""),
(s) =>
if Text.Proper(caseType ?? "Upper") = "Upper"
then not (Text.Lower(s) = s)
else not (Text.Upper(s) = s)
)
@m-dekorte
m-dekorte / extendedDateTable.cs
Created March 11, 2025 11:34
Extended Date table C# script | Compatible with Tabular Editor versions TE2 and TE3
var dateTableName = "Dates"; // Name of your date table
var dateKeyColName = "Date"; // Name of the date key column in the table
var colOperations = new List<Tuple<string, string, bool>>(){
Tuple.Create("Quarter & Year", "QuarternYear", true),
Tuple.Create("Month & Year", "MonthnYear", true),
Tuple.Create("Month Name", "MonthOfYear", true),
Tuple.Create("Month Short", "MonthOfYear", true),
Tuple.Create("Month Initial", "MonthOfYear", true),
Tuple.Create("Week & Year", "WeeknYear", true),
Tuple.Create("Day of Week Name", "DayOfWeek", true),
@m-dekorte
m-dekorte / extendedDateTable.pq
Last active May 24, 2025 04:54
Extended Date table M function | Creates an ISO-8601 type calendar
let
fnDateTable = ( StartDate as date, EndDate as date, optional FYStartMonthNum as number, optional Holidays as list, optional WDStartNum as number, optional AddRelativeNetWorkdays as logical ) as table =>
let
FYStartMonth = List.Select({1..12}, each _ = FYStartMonthNum){0}? ?? 1,
WDStart = List.Select({0..1}, each _ = WDStartNum){0}? ?? 0,
CurrentDate = Date.From(DateTimeZone.FixedUtcNow()),
DayCount = Duration.Days(Duration.From(EndDate - StartDate)) + 1,
weekStart = Day.Monday,
HolidaysProvided = Holidays <> null,
@m-dekorte
m-dekorte / convertTo.pq
Created March 10, 2025 09:28
convertToDate* M function | Convert an input value like a date, datetime, datetimezone or text to a target type.
let
/* Function to convert an input value like a date, datetime, datetimezone, or text to a target type */
convertTo = let
fxConvertTo = (Value as any, ReturnType as text, optional Culture as text) as any =>
let
TypeSelector = List.PositionOf(AvailableTypes, ReturnType, 0, Comparer.OrdinalIgnoreCase),
BaseDate = DateTimeZone.From(Value, (Culture ?? Culture.Current)),
TypeValue = {Date.From(BaseDate), DateTime.From(BaseDate), BaseDate}{TypeSelector}
in
TypeValue,
@m-dekorte
m-dekorte / colRenamesAndTypes.pq
Created February 28, 2025 14:28
colRenamesAndTypes Example | manage renaming columns and setting column data types
let
colTypes = [
#"any" = Any.Type,
#"date" = Date.Type,
#"time" = Time.Type,
#"datetime" = DateTime.Type,
#"logical" = Logical.Type,
#"number" = Number.Type,
#"currency" = Currency.Type,
#"integer" = Int64.Type,
@m-dekorte
m-dekorte / getAllSubstrings.pq
Last active February 21, 2025 15:40
getAllSubstrings M function | Generate all possible contiguous substring combinations from a string.
let
/* This was an exercise just for fun. Who knows, it might have a real-world application... */
/* Generate every possible substring combination from a string */
getAllSubstrings = (s as text, optional makeDistinct as logical, optional ignoreCase as logical) as list =>
let
c = if ignoreCase ?? false then Comparer.OrdinalIgnoreCase else Comparer.Ordinal,
n = Text.Length(s),
sub = List.TransformMany(
{0..n-1},
each {_+1..n},
@m-dekorte
m-dekorte / errorReport.pq
Created January 26, 2025 11:24
errorReport M function | Creates a record with overall error count and detailed error reporting table.
let
fxErrorReport = (myTable as table, optional keyCols as list, optional scanCols as list ) as record =>
let
colNames = Table.ColumnNames( myTable ),
validKeys = List.Intersect( { colNames, keyCols ?? {} } ),
hasKeys = List.Count( validKeys ) >0,
selCols = List.Intersect( { colNames, scanCols ?? {} } ),
nTable = Table.SelectColumns( myTable, if List.Count( selCols ) >0 then validKeys & selCols else colNames ),
reservedNames = { "Name", "Errors", "Reason", "Message", "Detail", "rowIndex", "nCol" },
nameViolations = List.Intersect( { colNames, reservedNames } ),
@m-dekorte
m-dekorte / profileWithErrorCount.pq
Created January 26, 2025 11:18
profileWithErrorCount M function | Creates a table profile with statistics, including an error count for all columns.
(t as table) as table =>
Table.Profile(t,
{{
"ErrorCount",
each true,
each Table.RowCount(Table.SelectRowsWithErrors(Table.FromColumns({_})))
}}
)
@m-dekorte
m-dekorte / errorReplacer.pq
Created January 26, 2025 11:11
errorReplacer M function | Substitute error values in all or listed scanColumns with a specified value or null if no replacement is provided.
(t as table, optional replacementValue as any, optional scanCols as list) as table =>
let
colNames = Table.ColumnNames(t),
selCols = List.Intersect({colNames, scanCols ?? {}}),
replErrors = Table.ReplaceErrorValues(t,
List.Transform(
if List.IsEmpty(selCols) then colNames else selCols,
each {_, replacementValue}
)
)
@m-dekorte
m-dekorte / excel-lambda-trimChar.txt
Created November 11, 2024 10:56
λ Trim a leading and trailing, leading or trailing character repeatedly.
trimChar = LAMBDA(str, [char], [mode],
LET(
charToTrim, IF(ISOMITTED(char), " ", LEFT(char, 1)),
trimMode, IF(OR(mode = 1, mode = 2, mode = 3), mode, 1),
// Trim functions
trimStart, LAMBDA(s,
REDUCE(
s,
SEQUENCE(LEN(s)),
LAMBDA(a, _,