BankFileParsers 0.2.2
dotnet add package BankFileParsers --version 0.2.2
NuGet\Install-Package BankFileParsers -Version 0.2.2
<PackageReference Include="BankFileParsers" Version="0.2.2" />
paket add BankFileParsers --version 0.2.2
#r "nuget: BankFileParsers, 0.2.2"
// Install BankFileParsers as a Cake Addin #addin nuget:?package=BankFileParsers&version=0.2.2 // Install BankFileParsers as a Cake Tool #tool nuget:?package=BankFileParsers&version=0.2.2
BankFileParsers
Need something in .Net to parse BAI and SWIFT files
We're not sure what we need, so I plan on doing both, looks like just the BAI file for now:
TODO
- Start the project
- Parse the files
- Write parsed output to exact input
- override ToString() to clean up the Write Method
- Create a Translation class to take the parsed files into detail
- Handle the fund type "D"
- Use the new Transaction Detail object (more informative than the 010 code)
- Use the Currency Code to figure out the correct currency amount
- Create a method so the user can convert the amount
-
Take the translation and write the input fileDon't have time to do this right now - Output Summary and Detail to CSV files
SUMMARY/HEADER TABLE
I'm borrowing heavily from the Field Mapping for Automatic Bank Statement Processing, but I will only be using fields that are used in the BAI file
Table definition can be found here
See SummaryHeader for output
DETAIL TABLE
Table definition can be found here
See DetailSummary for output
USAGE
Install-Package BankFileParsers
The first class that you will need to use is the BaiParser
. It's actually pretty basic; it takes an existing BAI file and creates an object tree/graph
var parser = new BaiParser();
var bai = parser.Parse("--path to file--");
The bai
object created above will contain a thin object graph that follows this format
BaiFile
|-- List<BaiGroup>
|-- List<BaiAccount>
|-- List<BaiDetail>
So, a BaiFile contains a List of Groups, Each Group has a list of accounts; each account has a list of details - whew!
This actually follows the spec defined in the BAI document listed above.
You can in turn ask the parser to write the parsed data back out like so
parser.Write("--new filename--", bai);
This should create a file that is an exact match as the original file (100% matches on the four files I use in testing).
The parsed data may or may not be of any use to you. If you need more translation there is the BaiTranslator
This object is responsible for Translating the parsed data to something that could be more usable and the object graph is very similar to the one the parser creates.
var trans = BaiTranslator.Translate(bai);
This then returns a TranslatedBaiFile with List<Group>
, List<Account>
with List<Fund>
and List<Detail>
with the only object added is the List of Fund
Additions
The document states that the Detail can contain a Text field and those can have continuation records. This seems more like a free form text field and it's up to the financial institution to define what they put in there. Since this could mean anything I've added a TextList object that tries to parse each individual section in the text file into individual lines. For example you could have a text filed that looks like this (sensitive information redacted):
PREAUTHORIZED ACH CREDIT/PREAUTHORIZED ACH FROM:SOME BANK I 100115/ORIGINATOR ID:XXXXXXXXXX4108/ENTRY DESCRIPTION:DESCRIPTION HERE/PAYMENT ID:105XXXXXX/RECEIVER INFORMATION:YOUR BANK ACCOUNT/TRACER ID NUMBER:XXX27400XXXXXXX/ADDENDA INFORMATION:/TRN*1*XXXXXXXXXXXXXXX*XXXXXXXXXX/,XXXXXXXXXXXX/
This could be something else that needs to be parsed - and TextList does just that - detail.TextList would look like this for the previous line
[0] = PREAUTHORIZED ACH CREDIT
[1] = PREAUTHORIZED ACH FROM:SOME BANK I 100115
[2] = ORIGINATOR ID:XXXXXXXXXX4108
[3] = ENTRY DESCRIPTION:DESCRIPTION HERE
[4] = PAYMENT ID:105XXXXXX
[5] = RECEIVER INFORMATION:YOUR BANK ACCOUNT NAME
[6] = TRACER ID NUMBER:XXX27400XXXXXXX
[7] = ADDENDA INFORMATION:TRN*1*XXXXXXXXXXXXXXX*XXXXXXXXXX
[8] = XXXXXXXXXXXX
I then noticed that several TextLists had similar names or a key:value so I added TextDictionary to the detail object and that would look like this (JSONified)
{
"PREAUTHORIZED ACH FROM": "SOME BANK I 100115",
"ORIGINATOR ID": "XXXXXXXXXX4108",
"ENTRY DESCRIPTION": "DESCRIPTION HERE",
"PAYMENT ID": "105XXXXXX",
"RECEIVER INFORMATION": "YOUR BANK ACCOUNT NAME",
"TRACER ID NUMBER": "XXX27400XXXXXXX",
"ADDENDA INFORMATION": "TRN*1*XXXXXXXXXXXXXXX*XXXXXXXXXX XXXXXXXXXXXX"
}
Since the TextList and TextDictionary are additions to the spec I would not count on them containing any data (they will not be null however).
While browsing options that were out there for the BAI file I ran into a utility that would translate the BAI file into two CSV files. I've replicated those in the
BaiTranslator.GetSummaryInformation
and BaiTranslator.GetDetailInformation
helpers and they are used like to
var summary = BaiTranslator.GetSummaryInformation(trans);
This returns a List<SummaryHeader>
and each of the fields are marked with a Usage attribute that specifies if they were from
Oracle, TreasurySoftware, or Both, the attribute isn't necessary, but you could use it to figure out why it's there.
var dictionaryKeys = new List<string> { "PAYMENT ID", "ADDENDA INFORMATION" };
var detail = BaiTranslator.GetDetailInformation(trans, dictionaryKeys); // dictionaryKeys can be null
This returns a List<DetailSummary>
again, each of the fields are marked with a Usage attribute
Note: The dictionaryKeys are a list of Key names that could be in the TextDictionary object that you would like returned. If it's found in the detail object, it's returned in the DetailSummary - think of it like a filter. This could be handy if the detail TextDictionary finds 18 key/value pairs and you're only concerned with one or two of them
You can use the two lists above as is, or you can use a helper extension method to generate CSV data, and you would use it like this
var csv = detail.ExportToCsv();
File.WriteAllText(@"BAI-sample.csv", csv);
This will put all fields in the detail object in a list of CSV (with a header). You can use the two optional parameters to specify which fields you would like to export as well as which dictionary keys you would like to export. You can use it as so:
var csv = detail.ExportToCsv(dictionaryKeys, new List<string> {"Date", "Amount"});
File.WriteAllText(@"BAI-sample.csv", csv);
Dictionary keys are appended to the normal csv output. A clever person could see that using reflection they can get a list of the field names with a usage type of Oracle and Both to just export the fields defined/used there.
So the above code would create a csv file that would look like so:
Date | Amount | PAYMENT ID | ADDENDA INFORMATION |
---|---|---|---|
10/12/2015 | 100.00 | xxxxx | TRN1XXXXXXXXXXXXXXX*XXXXXXXXXX XXXXXXXXXXXX |
10/12/2015 | 200.00 | yyyyy | TRN2XXXXXXXXXXXXXXX*XXXXXXXXXX XXXXXXXXXXXX |
etc...
This is all it was intended to do - add an issue or pull request and we can make some changes
CHANGE LOG
[0.2.1] - 2023-06-01
Changed - possible breaking change
- I finally got a file that showed me what was happening in issue #9, this should be fixed now.
[0.2.0] - 2023-05-31
Changed - possible breaking change
- Added net7.0 TFM (Target framework moniker)
- I have a new bank, the format is quite a bit different. This version 'should not' break existing functionality, but I don't have your files, so I can't guarantee it. The change is how the BaiTranslator handles continuation records (88's). The old way (which is the default) just did a string += otherString. The new option does a TrimEnd('/') + Environment.NewLine. This made it WAY easier for me to handle that data. I also didn't want to pass values to several objects, so it's a static property (not really a fan, but easy).
- Setting
BaiTranslator.BaiTranslator88LineHandler = BaiTranslator88LineHandler.TrimSlashNewLine
before calling BaiTranslator.Translate will get you the new functionality. - Leaving it alone, or setting it to
BaiTranslator.BaiTranslator88LineHandler = BaiTranslator88LineHandler.OldWay
works the old way. I tested this with several files and it still worked (woot).
- Setting
- The new Translator returns the full dictionary of items if it finds any, so you might not need to use keys. Keys still work however.
- Sorry for the lack of imagination on my end.
[0.1.10] - 2022-09-21
Changed
- Via PR #23 - added two methods:
- ParseText() - takes BAI file contents as a string, instead of BAI file name
- GetFileText() - returns parsed BAI file contents as a string array, instead of writing to a file.
[0.1.9] - 2022-08-22
Changed
- Via PR #19 - added the ability to overwrite the Transaction Detail Line
[0.1.8] - 2022-07-01
Changed
- Added license to nuget package to remove pack warning
[0.1.7] - 2022-07-01
Changed
- Added .net standard, core and .net 6 support TargetFrameworks: net4.5;netstandard2.0;netstandard2.1;net5.0;net6.0
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net45 is compatible. net451 was computed. net452 was computed. net46 was computed. net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.5
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
-
.NETStandard 2.1
- No dependencies.
-
net5.0
- No dependencies.
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.2.2 | 1,201 | 4/17/2024 |
0.2.1 | 488 | 6/1/2023 |
0.2.0 | 200 | 5/31/2023 |
0.1.10 | 3,048 | 9/21/2022 |
0.1.9 | 453 | 8/23/2022 |
0.1.8 | 2,556 | 1/7/2022 |
0.1.7 | 8,644 | 1/7/2022 |
0.1.6 | 9,119 | 9/23/2021 |
0.1.5 | 9,577 | 2/10/2016 |
0.1.4 | 1,880 | 11/13/2015 |
0.1.3 | 1,470 | 10/22/2015 |
0.1.2 | 1,462 | 10/13/2015 |
0.1.1 | 1,406 | 10/13/2015 |
0.1.0 | 1,400 | 10/13/2015 |