4

ANSI 835(テキスト)ファイルがあります。簡単にするために、次のようになります。

ISA*00
GS*Foo*12345
ST*835*000001
LX*1
CLP*123456
NM1*Lastname
REF*010101
DTM*20120512
SVC*393939
LQ*19
LX*2
CLP*23456
NM1*Smith
REF*58774
DTM*20120601
SVC*985146
LX*3
CLP*34567
NM1*Doe
REF*985432
DTM*20121102
SVC*864253
LQ*19
LQ*84

レコードはLXセグメントに分割されます。LX * 1以降はすべて1つのレコードであり、LX*2以降はすべて別のレコードです。各行から特定のアイテムを取得し、それらを変数に割り当て、最終的にそれらを行としてdatagridviewに追加する必要があります。簡単にするために、次の変数があります。それぞれに何を入れる必要がありますか。

string ItemNumberCLP行の*の後の
string LastName文字のグループである必要がありますNM1行の*の
string Date後の文字のグループである必要がありますREF行の*の
string Error後の文字のグループである必要がありますLQライン

私が直面している最大の問題は、各LXセグメントに複数のLQラインが存在する可能性があることです。その場合、2番目のエラーを最初のエラーの最後にコンマで区切って追加することができます。

ファイルを文字列配列にロードして行ごとに試しましたが、「LX * 1から始めて、LX*2に到達するまで何かを実行する」と言う方法がわかりません。

string[] lines = File.ReadAllLines(MyFile);

foreach (string line in lines)
{
    string[] splitline = line.Split('*');

    if (splitline[0] = "LX")
    {
        //this is where i need to loop through the next lines 
        //until i hit the next line starting with LX.
    }
}

何か案は?いつものように、お時間をいただきありがとうございます!

4

1 に答える 1

6

単純なデータ モデルから始めます。

public class LXRecord
{
    public string ItemNumber { get; set; }
    public string LastName { get; set; }
    public string Date { get; set; }
    public List<string> Errors { get; set; }

    public LXRecord()
    {
        Errors = new List<String>();
    }
}

重要なトークンを定義します。

public static class Tokens
{
    public const string TOKEN_SPLITTER = "*";
    public const string NEW_RECORD = "LX";
    public const string ITEM_NUMBER = "CLP";
    public const string LAST_NAME = "NM1";
    public const string DATE = "REF";
    public const string ERROR = "LQ";
}

行をループし、トークンで切り替え/ケースをLXRecord実行し、「LX」フラグが表示されたら新しいものを開始します。

List<LXRecord> records = new List<LXRecord>();
LXRecord currentRecord = null;

foreach(string line in lines)
{
    int tokenIndex = line.IndexOf(Tokens.TOKEN_SPLITTER);
    if (tokenIndex < 1 || tokenIndex == line.Length - 1) //no token or no value?
        continue;

    string token = line.Substring(0, tokenIndex);
    string value = line.Substring(tokenIndex + 1);

    switch(token)
    {
        case(Tokens.NEW_RECORD) :
            currentRecord = new LXRecord();
            records.Add(currentRecord);
            break;
        case(Tokens.ITEM_NUMBER) :
            currentRecord.ItemNumber = value;
            break;
        case(Tokens.LAST_NAME) :
            currentRecord.LastName = value;
            break;
        case(Tokens.DATE) :
            currentRecord.Date = value;
            break;
        case(Tokens.ERROR) :
            currentRecord.Errors.Add(value);
            break;
    }
}

このようにして、サポートされていないフラグを比較的簡単に無視したり、新しいフラグを追加したり、解析を追加したりできることに注意してください (たとえば、整数としてItemNumber使用して保存したり、「日付」に を保存したりできます)。エラーは として表示されますが、必要に応じてカンマで区切ることもできます。また、コンテンツに 2 番目のアスタリスクが含まれている場合に備えて、文字の分割も避けました。Int32.ParseDateTimeList<String>*

編集:あなたのコメントから、より複雑で特殊な解析を行うcaseか、別のメソッドに移動することができます。上記の「LAST_NAME」のケースの代わりに、次のようにすることができます。

case(Tokens.LAST_NAME) :
    ParseName(currentRecord, value);
    break;

どこParseNameにある:

public static void ParseName(LXRecord record, string value)
{
    int tokenIndex = value.IndexOf(Tokens.TOKEN_SPLITTER);
    if (tokenIndex < 1 || tokenIndex == value.Length - 1) //no last name and first name?
    {
        record.LastName = value;
    }
    else
    {
        record.LastName = value.Substring(0, tokenIndex);
        record.FirstName = value.Substring(tokenIndex + 1);
    }
}

トークン チェックはそこで微調整される可能性がありますが、良いアイデアが得られるはずです。

于 2013-02-06T21:16:23.723 に答える