What is Fixed record?
Fixed record refers to the structure of various data formats at the lowest level. Whereas CSV separates the individual values from each other using special separator characters, here it is the lengths of the values that are key. And – much like CSV – so is their order. As a result of these two requirements, each value in the record has a precisely fixed start and end position.
A simple example?
OH 4711 K0815 20130530
This an extremely simple example, but it covers the basics.
Let’s go through each line in detail.
OH 4711 K0815 20130530
- OH stands for order header here. This is the record type identifier that allows the software (or a human) to recognise what kind of record is being transmitted.The identifier is always three characters long, and is completed here with a space.
- 4711 is the order number, which is eight characters long and completed with spaces.
- K0815 is the customer number, which has the same length and is completed in the same way.
- 20130530 at the end is the order date, in yyyymmdd format (i.e. 8 characters long).
- Behind that comes another space, only you can’t see it right now (though you will later).
- LIN is the line item identifier. Because it already takes up three characters, there is no need to add a space to it.
- 0001 is the item number. It has a length of four characters and is completed with leading zeroes.
- S123 is the item number, followed by spaces to take it up to eight characters.
- 0005 is the quantity, which is four characters long, with zeroes added to take it up to the character limit.
- 000009990 represents 9.99, completed with filler zeroes before the value. Instead of using a decimal separator, it is simply specified that the last three digits represent the numbers after the decimal point. Total length 9.
Now, add the lengths of these different fields together. What do you get? 28, both times. To achieve this, a space is added to the end of the header line. If there were more than these two record types, they would all need to be long enough to make room for the longest one. Alternatively, you can just choose a standard computing number such as 64,
128 or 256. This is fairly typical for data formats of this kind, but not really compulsory. In principle, every record type can have its own unique length; however, that length would then need to be precisely defined.
By applying the rule that every record type must be the appropriate length, we can dispense with line separators (which are incompatible with many systems) and put everything together in one long sequence:
OH 4711 K0815 20130530 LIN0001S123 0005000009990LIN0002H456 0003000017950
Now you can see the space at the end of the order header.
Record type identifiers
An individual message is typically made up of various parts. These might include a header (as in the example above), and often a trailer record at the end, as well as information on individual shipments, call-offs etc., details on line items, and so on. In many formats, the record type appears right at the beginning. This is extremely practical, as we can then apply just one simple rule:
Look at the first characters of the file to find out what the record type is. With the help of the format definition, we now know how long this record type is and what values appear where. And then we simply need to look at the following characters to find out what is coming next.
Rules in practice
All this talk of exact lengths for each record type is very nice in theory, but there are a few variations in practice. If we are taking a purist approach, then every record type really will need to be exactly the right length and have spaces added to fill up any unused characters. In addition, there is no line separation – everything is printed in one long sequence. That’s
great for machines to read, but not particularly pleasant for humans (see above). As such, individual records are often separated from each other by line breaks in practice.
Yet that in turn isn’t so great for the computer, since it will read the line breaks as extraneous characters and will need to take them into account when calculating the lengths of the records. In other words, a record type with 128 characters will in fact have 129 or 130 characters (LF or CRLF).
If we do separate the record types with line breaks, we can also omit the filler characters at the end while we’re at it. As a result, the header record above would suddenly be only 27 characters long, instead of the formally required 28 characters. This isn’t exactly what we initially expected from this format, but you will encounter these variations time and time again out in the wild.
There are a few other rules that aren’t necessarily compulsory, but are sometimes applied
in recognised fixed-record data formats:
- Numerical values are generally brought up to their defined character length using leading zeroes.
- Non-numerical values, by contrast, are completed using spaces added to the right of the actual value.
- Floating-point numbers generally aren’t represented using decimal separators; instead, we use a fixed number of implicit decimal places. For example, 3.05 (with leading filler characters) would become 00003050. The last three characters here are implicit decimal places. The number of decimal places in each case is usually specified individually for each value.
- Dates and times can also normally be written without a separator, and the formats yymmdd or yyyymmdd and hhmm or hhmmss are widely used instead.
- The record type identifiers generally appear at the beginning of the record – however, there are also formats (typically company-specific ones) that place the identifier somewhere in the middle of the data.
- Of course, if there is only one kind of record then we can dispense with identifiers altogether.
Data formats based on fixed record
The two best-known exponents are Fortras and VDA (discussed here in their older formats). Both of these were developed and adopted by consortiums, and are discussed in their own dedicated articles. Then there is also the older IDoc format from SAP, which also forms the subject of its own asection. However, exports from databases (for example) are also often structured in this way – especially when the data come from an AS/400 (IBM iSeries). Every column in the table then has its own defined length, and often everything is written in one column in a single standard-length string. A few other programs also use files in fixedrecord format for imports and exports, as they are very easy to read. You simply move the file pointer along by e.g. 128 characters each time in order to automatically reach the next data set – and even within a single data set, you can just jump to the positions specified at the beginning in order to find the desired values. Back when most programs still stored their data in custom structures on CDs (or even floppy disks) instead of using generally accessible databases (which weren’t so readily available back then), this was the most practical solution for situations when not everything would fit on the storage medium.
What is VDA?
The acronym VDA doesn’t actually stand for a data format – rather, it is short for the Verband der deutschen Automobilindustrie (the German Association of the Automotive Industry). This organisation has issued a set of recommendations to its members on how they should share their data with each other in the context of EDI. These recommendations come with numbers which stand for different message types.
The earlier recommendations still contain custom formats which – in terms of structure – are fixed-record formats. It is these that we will look at in this chapter. Since then, the VDA has been changing tack towards using EDIFACT (one example of this can be found in VDA recommendation 4938), which is gradually giving rise to a special subset (cf. the chapter on EDIFACT).
Common types (or recommendations) include 4905 (call-offs), 4906 (invoices), 4913 (delivery notes) and 4920 (forwarding instructions), but there are many others beyond these. Why do they all start with 49? Ask us an easier question! You can find a long list of available recommendations in the Wikipedia article on VDA.
Don’t be surprised at the different names for the record types – these can be freely chosen in this software and are something of a matter of taste. One person might be happy with “N[ode] 711”, while somebody else might prefer the more detailed R[ecord]T[ype]_511_Header_Call-Off Data”.
51101CuNo SuNo 0045600457130209 |END
This (i.e. everything that comes before “|END”) is the file header for a VDA 4905 call-off.
The individual values are:
- 511: The header identifier – always three characters.
- 01: The version number – always two characters, with a zero at the start as a filler character, if necessary.
- CuNo: Customer number – always nine characters, with spaces at the end as filler characters, if necessary.
- SuNo: Supplier number – likewise nine characters with spaces as fillers at the end.
- 00456: The serial number of the preceding order – always five characters with leading zeroes as filler characters.
- 00457: The serial number for this order – with the same length and filler characters as for the previous order.
- 130209: The date of the transfer in yymmdd format – in this case, February 9, 2013.
Here, we have displayed the structure of this record in a more tabular format:
Now, add the lengths of these different fields together. What do you get? 128. And every other record type in a VDA 4905 call-off will also be exactly 128 characters long. In order to achieve this, a certain number of filler spaces are added to the end of each line.
Basic rules of VDA
Every VDA message begins with a header containing the parties involved, the numbers of the preceding and current transfers, and the date of the transfer. In most cases, a few other pieces of information will also be included, but this will vary from type to type.
Equally, every message will end with a trailer stating the number of individual record types within the message.
It almost looks as though record type 717 appears later in the message, since its counter comes after that belonging to the trailer (719).
Incidentally, every record type starts with an identifier (three characters) and a version number (two characters, with a filler zero if required). This version number really does refer to the individual record type. As such, you will sometimes find all kinds of record types from different versions rubbing shoulders within a single message. Numerical values are generally brought up to the necessary length with leading zeroes, while all other values use trailing spaces as filler characters.
What is Fortras?
Today, Fortras represents a messaging standard that is used for data interchange with or between haulage companies. Fortunately, it’s relatively straightforward. There are three commonly used message types: consignment information, status reports and unloading reports. These in turn exist in multiple versions, or releases. Releases 2 to 5 (release 1 was skipped from the outset) contain all three message types, and release 6 saw a few minor changes to the consignment information message, while in release 100 all three message types were completely overhauled.
Since one obvious difference between these versions is the length of the individual record types (128 characters in releases 2 to 6, 512 characters in release 100), we can summarise the full diversity of standard Fortras messages in the following short list:
- Releases 2–6 with 128-character records:
- BORD128: Consignment information
- STAT128: Status data
- ENTL128: Unloading report
- Release 100 with 512-character records:
- BORD512: Consignment information
- STAT512: Status data
- ENTL512: Unloading report
And to go with that, here is an example of just such a file, stripped back to only the record type identifiers and a few key values:
@@PHBORD512 1234 56 7 8 SENDER RECIPIEN
A00STDShipment header data
B00001SHPSender information Shipment 1
D00001001Packages, Line items, Weights etc.
B00002SHPSender information Shipment 2
… the second shipment …
J00Totals for all shipments
It may seem a little strange that the record types B00 and B10 appear twice in the source structure above – once with the suffix “-SHP” and once as “Adresse_Rest” (Address_remainder” in English). The reason for this can be found in the data: Each shipment in the file begins with the sender’s address details (SHP = shipper). However, this can be followed by various other address details, such as those of the recipient (CON = consignee). And each of these addresses comes with additional contact information, such as the telephone number contained in the B10 record. It is this logic – that the SHP address appears at the start of the shipment – that we have displayed in the source structure in this special way.
As we have already mentioned, every record type in Fortras release 100 is 512 characters long. That means that in a real-life file, every line will typically come with filler spaces to bring it up to the correct length if the data within the line doesn’t contain enough characters. And as we saw in the general article about fixed record format, this is only done when we need to adhere strictly to the fixed record length. However, if we use line breaks instead, we can happily omit the filler characters at the end.
Two lines merit our closer attention here: the ones beginning with @@.
@@PHBORD512 1234 56 7 8 SENDER RECIPIEN
All Fortras formats begin with a line like this. @@PH always comes at the beginning, followed by the format code taken from the list above (i.e. anything from BORD128 to ENTL512), which in turn is followed by information about the sender and recipient of the data and a few other small details.
indicates the end of the file.
As with VDA, numerical values take leading zeroes as filler characters, while other values are brought up to the required length using trailing spaces. Fortras also uses implicit decimal places, so that 3.05 (for example) becomes 00003050.