8000 Read the Blob of forms as a tree, and check every value against SaveAsText by dominion525 · Pull Request #103 · dominion525/jetdb · GitHub
[go: up one dir, main page]

Skip to content

Read the Blob of forms as a tree, and check every value against SaveAsText - #103

Merged
dominion525 merged 18 commits into
mainfrom
feature/form-blob-tree
Oct 19, 2026
Merged

dominion525 merged 18 commits into
mainfrom
feature/form-blob-tree

Conversation

@dominion525
Copy link
Copy Markdown
Owner

Summary

  • Read the Blob of forms and reports of Access 2002 and later as the tree the Access 2000 format keeps: the trailer 253, 254 or 255 that ends a group of entries tells none, one or a count of nodes after it, each node being a section or control with its type (acControlType). All 348 such Blobs of the test data read to their last byte. The properties a control keeps before its Name, such as Left, Top, Width and Height, are now read
  • form controls and formControls list the sections and controls from that tree instead of TypeInfo, which is empty for forms and reports made by VBA, where they failed, and can keep an old spelling of a name or garbled names. The order is that of the Blob, each section followed by its controls, as form props shows them, and the third column (index) is the place in the list
  • The type of a control is that of TypeInfo for the control of the same name, ignoring case, or else that of the tree; TypeInfo is no longer looked up by index, which gave some controls the type of another one. TypeInfo names are read in the code page of the database instead of Shift_JIS, and the 36 bytes the entry of an ActiveX control has after its names are passed over, which made the entries after it read wrong
  • Name the types of the tree for ActiveX controls and for the page and group sections, and give three text properties the names their SaveAsText values agree with: 0x00A0 DatasheetFontName, 0x010A Tag, 0x015A ColumnInfo (0x015A is no longer InputMask)
  • Access 2000 format: the properties of the form or report itself start right after its type, at byte 10, not 12, where its first two properties were dropped; and ten pairs of its IDs with those of Access 2002 and later now follow the names of its own SaveAsText output, such as BorderColor, which was paired with GridlineColor
  • A new test checks every value jetdb reads of the forms and reports of Sports.accdb, whose SaveAsText files fetch-testdata.sh now fetches, of the two databases made by Access for Microsoft 365, which keep their output in tblGenExport, and of their Access 2000 versions, whose own output is added to testdata/V2000/saveastext: each value is in the block of the same control, the controls and blocks are one to one with as many NotDefault values, the values of an ID are under one key no other ID holds, and a named ID is under its name alone
  • Update docs/form-design and docs/cli (en/ja)

🤖 Generated with Claude Code

dominion525 and others added 18 commits October 19, 2026 12:03
- The 42 values of 0x015A the controls of Sports.accdb keep before their names all differ from their InputMask in SaveAsText, so drop the name from prop_id_name and from docs/form-design.md and docs/form-design.ja.md

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Access does not tell names apart by case, and TypeInfo can keep an old spelling of a name, such as H_Code in Sports.accdb for the control the Blob and SaveAsText name H_code
- Move the lookup by name into type_info_by_name, which compares the names in lower case

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- They were read in Shift_JIS, which garbled names in other languages
- AccessStorage keeps the code page in the header of the database, in which parse_type_info reads them, and decode_shift_jis goes
- The names are in the code page of the Access that saved the form, which the file does not keep: the header of Strings.mdb has 1252, and its Russian names are in 1251, so they stay garbled

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…cess 2000 format

- The Blob keeps, after the properties of the form itself, its default controls and its sections with their controls as a tree, and the trailers 253, 254 and 255 that end a group tell none, one or a count of nodes after it
- Read the sections and controls from the tree, with their properties before their names, and find each control by its Name entry as before only when the bytes do not read as a tree
- Give a control the type in the tree (its acControlType) when TypeInfo has no control of its name
- Test that the 348 Blobs of the test data read to the end as a tree, and raise the number of values checked against SaveAsText

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- TypeInfo can list the controls in another order than the Blob, so the index gave a control the type of another one, as in Hyphenate of Strings.mdb
- Use the type in the tree when TypeInfo has no control of the name, and 0 when there is none

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…he types of the tree of the Blob

- Add 0x0077 CustomControl, 0x009B PageHeader, 0x009C PageFooter, 0x009D GroupHeader and 0x009E GroupFooter to control_type_name
- Each is the low byte of the types TypeInfo gives the same controls in the test
8000
 data, while 0x0099 and 0x009A stay unnamed, being the header and footer of a form or of a report

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Info

- Forms and reports made by VBA have an empty TypeInfo, for which form controls and formControls failed
- TypeInfo can also keep an old spelling of a name, such as H_Code, or garbled names, while the names in the Blob are those of SaveAsText
- List them in the order of the Blob, each section followed by its controls, with their places in the list as the third column and as index
- smoke.mjs now checks the controls of the report with an empty TypeInfo

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rols lists from it

- form-design (en/ja): describe the layout of the Blob as a tree and replace the section boundaries with its nodes, tell that TypeInfo can be empty or keep old spellings and that its names are read in the code page of the header, and drop the limitation of the properties before the Name
- cli (en/ja): give the heading, the description and the output example of form controls as a list of the sections and controls of the Blob
- js.rs: describe formControls and FormControl.index by the order of the Blob and the places in the list

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… agree with

- 0x00A0 is DatasheetFontName rather than FontName and 0x010A is Tag rather than LabelType, and 0x015A is named ColumnInfo
- Every value of each matched that key in the SaveAsText output of the 116 forms and reports of Sports.accdb and in the tblGenExport tables of the four generated databases: 349 values of 0x00A0, 588 of 0x010A and 42 of 0x015A
- Correct the table of docs/form-design (en/ja) and tell what the names were checked against

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t output

- Take the 116 forms and reports of Sports.accdb, whose other 114 SaveAsText files fetch-testdata.sh now fetches, and the tblGenExport tables of the four generated databases
- Check that each value is in the block of the same control, that the controls and the blocks are one to one with as many NotDefault values, that the values of an ID are under one key no other ID holds alone, and that a named ID is under its name and no other key
- Compare bytes, GUIDs and the date and time of RecSrcDt too, and leave out, each with its reason, the values SaveAsText does not write and what these files cannot show
- Read SaveAsText in the test-only module save_as_text.rs, replacing the test that checked the integers of two objects

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…olds

- Move the comparison of bytes out of holds into holds_bytes, and the lines of a binary value out of Reader::line into binary_line
- Split checked_values, which checks one database, and check_agreement, which checks them against each other, out of the test

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ht after its type

- The header has 8 bytes, followed by the type of the form or report itself (0x96, 0x97) and its properties; passing over 12 bytes dropped its first two properties, NotDefault values, and made the reading of Form_AllowLayoutView_1 start inside a property with a value
- Found by the SaveAsText output of the files of this format themselves (Version =19), which has two NotDefault values more for every form and report; add the module that wrote it and its 202 files to testdata
- Test that the properties of base_Form and Form_AllowLayoutView_1 start as their SaveAsText output does

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t names them as

- The pairs were chosen by the values the same objects hold in the files made by Access for Microsoft 365, which tied some properties to another one always holding the same values there
- Pair 0xA0 of a form (DatasheetGridlinesColor) with 0x013F rather than 0x0247, BorderColor of seven types of control with 0x0008 rather than 0x01CF (GridlineColor), and DisplayWhen and BackStyle of a tab control with 0x0095 and 0x001D (a number) rather than 0x028A and 0x0289 (a Yes/No)
- Saving in the Access 2000 format, Access writes the value of DatasheetGridlinesColor12 as DatasheetGridlinesColor, so the test comparing the values of both formats compares 0x013F with 0x0247

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…sText output

- They were checked against tblGenExport, the output of the .accdb before it was saved in that format, which could not show the values of the IDs without a pair or the number of NotDefault values, and were left out for that
- Check them against the output in testdata/V2000/saveastext, in Shift_JIS, requiring every value, with those of the IDs without a pair, and as many NotDefault values, and drop the converted rule
- Compare the text of an ID without a pair, which jetdb gives as bytes, with the UTF-16LE bytes of the text of SaveAsText
- This test fails with the header of 12 bytes, by the number of NotDefault values, and with the old pairs, by the IDs holding two properties

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…y the names of SaveAsText

- form-design (en/ja): give the Blob of the Access 2000 format as 8 bytes of header, the form or report itself (its type and properties), and a list
- Tell that the pairs were checked against the SaveAsText output of the files of that format themselves, 381 of the 386 the data has being under keys of the same name and four not told apart, that the ten pairs where the names and the values point to different IDs follow the names, and that Access writes the value of DatasheetGridlinesColor12 as DatasheetGridlinesColor

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Only the BackStyle of a tab control, wrongly paired with UseTheme, gave its value as a Yes/No, and clippy found the kind unused once it was corrected
- Tell in the comment over the tables that a pair follows the name the SaveAsText output of the 2000 format gives

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ty thresholds

- Move the exception comparing 0x013F with the value of 0x0247 into holding

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The entry of an ActiveX control (acCustomControl, 0x77 in the low byte of its type) has the class ID and the ID of the type library of the control, 16 bytes each, and 4 bytes after its names; read as the next entry, they gave the entries after it in Hyphenate of Strings.mdb wrong names and types
- All 553 TypeInfo streams of the test data now read to their last byte; the only ActiveX control the test data has is the spin button of Microsoft Forms 2.0
- Test that the entries of Hyphenate have the types of the controls of their names in the tree of the Blob
- Split parse_type_info into type_info_count for the header, type_info_entry for an entry, and nul_terminated

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@dominion525
dominion525 merged commit 62b94d3 into main Oct 19, 2026
10 checks passed
@dominion525
dominion525 deleted the feature/form-blob-tree branch October 19, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0