A free function rather than a member of IExternalBook, deliberately. It is a projection of
getSources(), and "the file's name" is already IWorkbookIO.Origin's vocabulary, where
getName() is the name WITHOUT its extension and getExtension() is separate. A second,
conflicting spelling of that noun on a neighbouring interface is how the two get confused.
The book role entry is the path the source is opened from and is sorted first by the reader, so
the first entry is the one to read. An xlPathMissing target is a bare name rather than a URI and
has no separator to split on, which this handles by finding none.
The name Excel writes INSIDE the brackets —
Budget.xlsxin[Budget.xlsx]Sheet1: the last segment of the book's first source, URL-decoded.