The Parse That Throws
The warehouse imports a spreadsheet of purchase references and lead times every morning. Rows 1 to 4,999 are fine; row 5,000 has 12.5 in a whole-number column — and the whole batch dies with a runtime error. The culprit is one line of AL: Evaluate(Qty, Cell). Evaluate returns a Boolean, and its documentation is explicit: if you omit that return value and the conversion fails, a runtime error occurs. The starter code makes exactly that mistake, and a few related ones. Your job is a parser that reports bad input as false and never raises.
Requirements
Create a codeunit named "Safe Parser" with two public procedures:
procedure TryParseReference(Ref: Text; var Prefix: Text; var Year: Integer; var Seq: Integer): Boolean
procedure TryParseLead(Input: Text; var Lead: Duration): BooleanRules for TryParseReference:
- A reference looks like
INV-2026-000123: exactly three segments separated by hyphens — a prefix, a year and a sequence number. Two segments or four segments make the reference invalid. - The prefix is the first segment, returned exactly as written. It must be at least one character long.
- The year and the sequence number are whole numbers that fit in an
Integer. Leading zeros are padding:000123is 123. A decimal such as12.5, a word, or a number too large for anInteger(3000000000) makes the reference invalid. - A valid reference returns
truewith all three output parameters filled in. Anything else returnsfalse— never a runtime error, whatever the input is. When the result isfalse, callers do not rely on the output parameters (not graded).
Rules for TryParseLead:
Inputis a lead time written in words, such as2 days 4 hoursor90 minutes.Evaluateinto aDurationvariable understands this format natively —day(s),hour(s),minute(s),second(s)and their abbreviations — so no arithmetic is required.2 days 4 hoursis a duration of 52 hours;90 minutesis one and a half hours.- Text that is not a duration (
soon) and an emptyInputreturnfalse. Never a runtime error.
Pick object IDs in the 50100–50199 range, and reference other objects by name, never by ID.
The traps
Each of these is a method whose failure mode is an error rather than a return value, and each shows up in the starter or in a tempting rewrite of it:
Evaluatereturnsfalsewhen the text cannot be converted — including a number too large for the target type — but only if you use the return value. Discard it and the failure becomes a runtime error.Text.Splitreturns aList of [Text].Get(3)on a list that holds two elements raises an error; checkCountfirst, or use theGetoverload with avarparameter, which returnsfalseinstead.Text.IndexOfreturns 0 when the value is absent — check for that before using the position, because bothSubstringandCopyStrraise an error for a position below 1. They differ only in the length:CopyStrclamps a length that runs past the end of the text, whileSubstringonly tolerates that from Business Central 27.1 onward and raises an error on earlier versions.
What the tests check
The grading tests call TryParseReference with INV-2026-000123 (expecting true, INV, 2026 and 123) and with a generated reference — a random uppercase prefix, a random year and a random zero-padded sequence number — so a solution that pattern-matches the example fails. They then expect false, and no error, for INV-2026 (missing segment), INV-2026-000123-COPY (extra segment), INV-2026-12.5 (decimal sequence), INV-2026-3000000000 (sequence too large for an Integer), INV-YEAR-000123 (non-numeric year), random letters without any hyphen, an empty text, and -2026-000123 (empty prefix). TryParseLead is called with 2 days 4 hours (expecting exactly 52 hours), a generated N days M hours text, and 90 minutes (expecting exactly one and a half hours), then with soon and with an empty text, both expecting false. Any runtime error raised by your code fails the test that triggered it.
Learn More
- Evaluate method — the optional Boolean return value, and the words a Duration string may contain.
- List.Get(Integer, var T) method — the overload that returns false instead of raising an error when the index is out of range.
- Text.Split method — splitting a text on a separator into a
List of [Text]. - Duration data type — a 64-bit number of milliseconds you can compare and do arithmetic with.
Evaluate returns a Boolean. When you call it as a bare statement, a failed conversion becomes a runtime error; when you test it inside an if, it is just false you can act on — and the same goes for a number too large for the target type.Text.Split gives you a List of [Text]. Check Count before calling Get, or use the Get(Index, var Value) overload that returns false instead of raising an error. An empty first element is your empty-prefix case.Evaluate into a Duration variable already understands text like 2 days 4 hours and 90 minutes — no arithmetic needed. Reject the empty input first, then return whatever Evaluate returns.