システムデータ形式ではなく、CSV形式がほしい

解決


bob  2004-09-06 08:42:39  No: 10804

文字列からカンマ区切りで加工したい場合、
定石なのはTStrings.CommaTextですが、
このプロパティはヘルプにも書かれている通り
システムデータ形式のため、スペースでも区切ってしまいます。
CSVはその名の通り”カンマ区切り”のため
スペースで区切るのはNGとなります。

皆さんはどの様にしていらっしゃいますか?

-----D6Proのヘルプから引用
"Stri,ng 1", "Stri""ng 2", String 3,String4

Stri,ng 1
Stri"ng 2
String
3
String4

ではなく、
"Stri,ng 1", "Stri""ng 2", String 3,String4

Stri,ng 1
Stri"ng 2
String 3
String4
がほしい。


take  2004-09-07 00:20:25  No: 10805

私の場合TStringListを継承したTStringListExクラスを作成しその
プロパティとしてCommaTextExを追加し、そこで対処しています。

フォームにEdit1、Edit2とListBox1、Button1を配置してテスト
してみました。
色々なパターンはチェックし切れていませんが質問にあった文字列は
正常に分解できました。

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TStringListEx = class(TStringList)
  private
    { Private 宣言 }
    function GetCommaTextExSub(const str : string): string;
    function GetCommaTextEx: string;
    procedure SetCommaTextEx(const Value: string);
  public
    { Public 宣言 }
    property CommaTextEx : string read GetCommaTextEx write SetCommaTextEx;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    ListBox1: TListBox;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{ TStringListEx }

function TStringListEx.GetCommaTextEx: string;
var
  i : Integer;
  s,ss : string;
begin
  ss := '';
  if Count > 0 then begin
    s := Strings[0];
    ss := GetCommaTextExSub(s);
    for i := 1 to Count-1 do begin
      s := Strings[i];
      s := GetCommaTextExSub(s);
      ss := ss + ',' + s;
    end;
  end;
  result := ss;
end;

function TStringListEx.GetCommaTextExSub(const str: string): string;
var
  s : string;
begin
  s :=StringReplace(str,'"','""',[rfreplaceall]);
  if Pos(',',s) <> 0 then begin
    s := '"' + s + '"';
  end;
  result := s;
end;

procedure TStringListEx.SetCommaTextEx(const Value: string);
var
  i : Integer;
  c : Char;
  s : string;
  f,f2 : Boolean;
begin
  Clear;
  f := False;
  f2 := False;
  for i := 1 to Length(Value) do begin
    c := Value[i];
    if c = '"' then begin
      if f2 then begin
        s := s + c;
        f2 := False;
      end
      else begin
        f2 := True;
      end;
      f := not f;
    end
    else if (f = False) and (c = ',') then begin
      Add(s);
      s := '';
      f2 := False;
    end
    else begin
      s := s + c;
      f2 := False;
    end;
  end;
  //if s <> '' then Add(s);
  Add(s);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  t : TStringListEx;
begin
  t := TStringListEx.Create;
  try
    t.CommaTextEx := Edit1.Text;
    ListBox1.Items.Assign(t);
    Edit2.Text := t.CommaTextEx;
  finally
    t.Free;
  end;

end;


bob  2004-09-07 03:35:10  No: 10806

ありがとうございます。

できました。
教えて頂いたクラスを元に多少修正して、利用したいと思います。

"Stri,ng 1", "Stri""ng 2" , String 3,String4
の時、2,3カラム目の頭にスペースが入るのと、
出力時に必ずダブルコーテーションにくくるだけですので
問題ないと思います。

ありがとうございました。


bob  2004-09-07 03:41:45  No: 10807

解決押し忘れ


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加