Why a name beats a hardcoded address
When you call ss.setNamedRange('BudgetData', range), Sheets stores a live pointer to those cells — not a snapshot of the A1 string. Insert three rows above row 2 and BudgetData now covers B5:E53 without a single script edit. The A1 address updated under the hood. Hardcoded strings like sheet.getRange('B2:E50') do not survive that insert; they silently read the wrong rows.
I have watched this bite people who built a working weekly import script, handed it to a teammate, and came back to corrupted reports because the teammate inserted a header section two weeks later. Named ranges are the fix.
The name is scoped to the Spreadsheet object, not to any particular sheet. That means getRangeByName('BudgetData') works from any function in the project, and from any sheet within the same workbook.