memoコンポ−ネントの内容保存と、呼出し再表示をするには?

解決


アンブレラ  2010-09-08 00:38:18  No: 39108  IP: 192.*.*.*

フォ−ム上でコメントを入れてもらい(複数行にわたる)デ−タベ−スに保存、後で呼び出してそれを表示する、というものを作ろうとしてます

①そこでmemoコンポ−ネントを利用すればいいと判断しました

②for文をMemo.lines.countでまわして1行の文字列にし、DBへ保存する
  →でもこの場合、後でSQLで取り出した時にmemoコンポーネントへ
    再展開する際、改行位置等が再現できないような気がします
    (指定文字数ごとに機械的に改行する位の手しか思いつかず、入力
      情報の再現とは程遠い表示になる?)

Q1:①で選択したmemoコンポーネントがそもそも的外れでしょうか?
Q2:複数行にわたる入力コメントの保存と再現表示について、一般的な
      手法を教えてください

おねがいします

編集 削除
HOta  2010-09-08 08:52:22  No: 39109  IP: 192.*.*.*

Memo.linesはTString型なので、テキストに保存するならSaveToFileで簡単にローカル保存できますよ。
デ−タベ−スに保存も大丈夫です。
そのままデ−タベ−スからMemo.lines.add('hogehoge').asstring);
で再現できます。

何を使うかは目的ごとに変えればいいことです。
この場合は大丈夫だと思います。

編集 削除
茶柱  2010-09-08 11:54:03  No: 39110  IP: 192.*.*.*

完璧なコードではありませんが、改行コードを別の文字列に変換してはいかがでしょうか。

(uses SysUtils)

・DB用に変換する時
strDBText := StringReplace(Memo1.Lines.Text, Chr(13)+Chr(10), '<br>', [rfReplaceAll]);

・DBからメモに戻す時
Memo1.Lines.Text := StringReplace(strDBText, '<br>', Chr(13)+Chr(10), [rfReplaceAll]);

この場合ですと、改行コードを「<BR>」に置き換えていますので、
本文に同じ「<BR>」の文字があったら意図せず改行されてしまいます。
もし用途にそのような懸念がある場合は、変換する文字を他に変えてください。##RET##とか。。

当方の環境:Delphi2007

編集 削除
Delphi大好き  2010-09-08 12:37:44  No: 39111  IP: 192.*.*.*

もしデータベースを修正される事があるのなら・・・

ftmemo(メモ型)というデータ格納方式があります。
データベースに、メモの内容をそのまま保存できます。

begin
  //エリアスの代わりに実行ファイルがあるフォルダに設定
  table1.DatabaseName := ExtractFileDir( Paramstr(0) );
  //この場合サンプル.dbを開く
  table1.tablename := 'サンプル';
  //メモという名前のmemo型をdbmemoコンポーネントのデータフィールドに設定
  dbmemo1.DataField := 'メモ';
  try
    //開く
    table1.Open;
  except
    table1.fielddefs.Add('メモ', ftMemo, 255, false);
    table1.CreateTable;
    table1.Open;
  end;
end;

編集 削除
Delphi大好き  2010-09-08 23:36:39  No: 39112  IP: 192.*.*.*

ミスがあることに気づいたので書き直しました。
まだミスあるかも知れません。

あとSQL使った参考書紛失したのでTable使ってます。すいませんm(__)m。

begin
  //エリアスの代わりに実行ファイルがあるフォルダに設定
  table1.DatabaseName := ExtractFileDir( Paramstr(0) );
  //この場合サンプル.dbを開く
  table1.tablename := 'サンプル';
  //メモという名前のmemo型をdbmemoコンポーネントのデータフィールドに設定
  dbmemo1.DataField := 'メモ';
  try
    //開く
    table1.Open;
  except
    table1.Close;
    table1.fielddefs.Add('メモ', ftMemo, 255, false);
    table1.CreateTable;
    table1.Open;
    //エリアスの代わりに実行ファイルがあるフォルダに設定
    table1.DatabaseName := ExtractFileDir( Paramstr(0) );
    //この場合サンプル.dbを開く
    table1.tablename := 'サンプル';
    //メモという名前のmemo型をdbmemoコンポーネントのデータフィールドに設定
    dbmemo1.DataField := 'メモ';
  end;
end;

編集 削除
アンブレラ  2010-09-10 05:54:53  No: 39113  IP: 192.*.*.*

皆さん早いをレスをありがとうございます
返答が遅くなりすいません

先ずはHOta さんのご回答を(変更点が少ない事もあり)参考にさせて頂いてます

DBからのデ-タ表示については
  Memo.lines.add('Query1.FieldByName('xxx').asstring');
で表示できました(直接デ-タベ-スに書き込んだ情報がmemoコンポ-ネント上に表示されました)

※本題から外れますが、Memoコンポ-ネントの理解不足が原因で、使用後の初期化
  がうまくいかずに、2回目以降の実行では前回使用行に行追加して内容
  が表示される現象が起きています
  Lines.addだからのはずですが、Memo1.Lines.Count=0と指定したところ、  このプロパティは参照専用で指定は不可だと怒られました…使用した行数が
  保持されたままです  どこで初期化できるんでしょう?


さて問題は「デ−タベ−スに保存」の文で悩んでいます
  Memo.lines.SaveToFile(’xx’);
でファイルとして書き出したものを、Query1.sql.add('Update  xx  set〜)の中で指定する文法がわかりません

for文で  s=s+  Memo1.lines[i]  等でmemo内容をsに一まとめにして、SQL文の中で指定すると出来そうにも思えますが、教えて頂いたSaveToFileを利用してないやりかたになります
SaveToFileはどういった利用法になるのでしょうか?

宜しくお願いします


茶柱さんの制御案もこの後試させてもらいます
(ありがとうございます)

Delphi大好きさんの、ftmemo(メモ型)コンポ-ネントの利用は思いつきま
せんでした 
別のフォ-ムで1つのmemo欄にしか対応しない、項目1つだけのテ−ブル
を使用するものがあるので、そこで提示頂いた案に挑んでみます
ftmemoの性質を調べるところからのスタ-トになりますが、ありがとうございます

編集 削除
HOta  2010-09-10 10:41:18  No: 39114  IP: 192.*.*.*

Memo1.LinesはTStrings型なので、Memo1.Lines.Clearで初期化します。
DBにはLinsの数だけレコードを書き込みます。
この場合は一行ごとの処理になります。

SaveToFileはローカルにファイルTStrings型のデーターを保存するものです。
LoadFromFileで保存したファイルから読み込みます。保存して読み込むなら、とても簡単です。

データーベースに保存するなら、ファイルにはせずに行ごとの処理を繰り返すか、Memo1.Lines.Textを保存するかでしょう。データーベースのFieldの持ち方も考慮しないといけません。

編集 削除
ぽむぽむ  2010-09-10 11:46:39  No: 39115  IP: 192.*.*.*

今更ながら、TDBMemoを使うのはだめなんでしょうか?
TDataBase, TTable(TQuery), TDataSource, TDBMemo を使い、
Table.Edit -> DBMemoに編集 -> Table.Post で、
ファイルに落とさなくても、改行があるなしとか考えなくても
勝手にコンポーネント側でやってくれませんか?

それができない事情があっての質問でしたら、的外れですけど。

編集 削除
Delphi大好き  2010-09-10 11:51:27  No: 39116  IP: 192.*.*.*

ftmemoはコンポーネントではなく、
ftstringやftintegerと同じデータベースの型ですよ。

dbMemoを使うことでdbTextboxと同じように扱えます。
因みにリッチエディット型や画像を格納できる型もあります。

当方では、
Delphi3  実践データベースプログラミング
という本で学習してました。
初心者でも解り易い、とても良い本でした。
データ型やSQLの文法、コンポーネントまで、
詳しく書かれているのでとても助かりました。

しかし紛失してしまったので、
Delphi5  実践データベースプログラミング
という本に買い換えました。
これも良書だと思います。
色々と忙しく、殆ど読めてない現状ですが。

そして、SQL書こうとして殆ど忘れてる自分に気づきました(笑)。

参考になれば幸いです。

編集 削除
アンブレラ  2010-09-13 22:17:07  No: 39117  IP: 192.*.*.*

返答が遅れまして、すいません

まず、その後色々とテストしてみたところ、複数行を一文にしてSQLでテ-ブ
ル格納するまでは一見よさげでしたが、SELECT文で逆にMEMOに展開する際に
改行されずに繋がって表示されてしまいました

テ-ブルへの格納時、for文でADDしていったのですが、LINE単位で操作して
いても、行の不足分をスペ−スで埋めたりはしないんですね
HOtaさんにご協力いただきあと一歩だったのですが、ここからは1行の字数に
対し、入力文字数を算出し、不足分をスペ-スで埋めるか、改行コ−ドの検出
を試みるしかないのかな?と考えてます

---
(そもそもの目的)更新ボタン押下で、フォ-ム上のeditやcomboboxのtext内容
と一緒に、数行にわたるFreeフォ−マットの長文(memo)を登録したり、更
新したりする事

ぽむぽむ さんの指摘される通り、TDBMemoを使用する方が適切なのかなと検
討していますが、手持ちの参考書にはTDBMemoの説明がないため、取りあえず
DelphiのHELPを今読み込んでいます・・・

Delphi大好き さん、頂いた貴重な情報を元に、週末大きな書店を数軒回って
みましたが、Delphiの参考書って・・・扱ってないんですね、amazonでも探
してみます(皆さんはどちらで入手されてるんでしょうか?)
世の中にもう少し出回っていてもよさげなんですが・・・

---

編集 削除
TS  2010-09-13 23:34:24  No: 39118  IP: 192.*.*.*

>まず、その後色々とテストしてみたところ、複数行を一文にしてSQLでテ-ブ
>ル格納するまでは一見よさげでしたが、SELECT文で逆にMEMOに展開する際に
>改行されずに繋がって表示されてしまいました
Memo1.Lines.Commmatextを保存、読み込み、代入しても上記の様になりますか。

編集 削除
Quest  2010-09-14 00:49:58  No: 39119  IP: 192.*.*.*

極単純に
保存するとき
Table1.FieldByName('MemoField').AsString := Memo1.Lines.Text;
読み出すとき
Memo1.Lines.Text := Table1.FieldByName('MemoField').AsString;
で出来ませんか?
データベースに何を使用するかによってTable1の部分がいろいろあったり
'MemoField'の型を何にするかとか検討が必要ですが
ちょっとしたコメント程度であればVARCHAR(8192)とかでも十分だと思います。
本当はBLOBとか使うのが本筋ですが、データベースにより
表現がいろいろあるので。

編集 削除
Delphi大好き  2010-09-14 09:45:59  No: 39120  IP: 192.*.*.*

Delphi関連の本は書店では中々入手困難です。
最新版Delphiでも、ネットでは英語版ぐらい位しか手に入らない状況・・・

自分の場合、ヤフオクやアマゾンで中古本を購入してます。

Delphiの良いところは各バージョンの互換性があるので、
極端な場合だとDelphi1の参考書をTurboDelphiで参考に出来たりします。
無論互換性がない部分もありますが・・・。

編集 削除
Delphi大好き  2010-09-14 12:18:53  No: 39121  IP: 192.*.*.*

以下で試したらきちんとメモ帳に改行されて表示できました。
SQLは完全に忘れてるので、またしてもTable使ってますが。

以下が作ってみたサンプルです。
参考になれば幸いです。

procedure TForm1.FormCreate(Sender: TObject);
begin
  table1.DatabaseName := ExtractFileDir( Paramstr(0) );
  table1.tablename := 'テスト';
  try
    table1.Open;
  except
    //エリアスの代わりに実行ファイルがあるフォルダに設定
    table1.DatabaseName := ExtractFileDir( Paramstr(0) );
    table1.fielddefs.Add('No', ftautoinc, 0, false);
    table1.fielddefs.Add('メモ行', ftstring, 255, false);
    table1.tablename := 'テスト';
    table1.CreateTable;
    //この場合サンプル.dbを開く
    table1.Active := true;
    table1.Edit;
    table1.FieldByName('メモ行').asstring := '一行目';
    table1.Insert;
    table1.FieldByName('メモ行').asstring := '二行目';
    table1.Post;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i1,i2:integer;
begin
  table1.Last;
  i1 := table1.FieldByName('No').asinteger +1;
  i2 := 0;
  while i1 > i2 do begin
    memo1.Lines.Add(table1.FieldByName('メモ行').asstring);
    table1.Prior;
    i1 := i1 - 1;
  end;
end;

編集 削除
HOta  2010-09-15 10:33:14  No: 39122  IP: 192.*.*.*

目的は、Memo1.Linesの内容を保存して、再現するのですね。
再現する場合に、何故スペ−スで埋めるのでしょうか?
Memo1.Linesの一行の文字数のプロパティは無いと思うのですが。

編集 削除
アンブレラ  2010-09-15 11:06:58  No: 39123  IP: 192.*.*.*

TS  さんありがとうございます

SQLで取り扱う対象をMemo1.Lines.Commatextとしたところ、1行の文字列単
位で(途中改行の場合はそのままで)復元できました
ありがとうございます

Quest さんにご指摘いただいた、Memo1.Lines.Text 案は、最初のころに
Memo1.Lines.add から修正した直後、該当行で「;」がないと、コンパイル
エラーになった為(まだmemoの性質をよく知らなかった事もあり)あまり深
くは考えずに別の手段を模索してました・・・でも今改めて指摘を受けて
考えてみると、できるはずではないのか?と気になりましたのでこちらも
再度試してみます、ありがとうございます

Delphi大好き さん、参考書の情報の件を含め今回いろいろとありがとうご
ざいました
次の新しいフォ-ムの中ではdbMemoを試そうと思っています
SQLを回避し、教えて頂いたtable1.xxxを使うのも手軽なところが魅力ですし

---
皆さん今回はありがとうございました
参考書が入手しにくい状況を振り返えますと、早いレスで皆さんのご協力、
大変ありがたかったです(こちらの返信が遅れて失礼しました)
また詰まった時には教えてください

編集 削除
アンブレラ  2010-09-15 11:30:29  No: 39124  IP: 192.*.*.*

HOta さんのご指摘へ

>Memo1.Linesの一行の文字数のプロパティは無いと思うのですが。

についてですが、最初memoのプロパティで入力文字を大文字固定にし、1行に
入れられる最大文字数を数えて決める。
そして、memo.lines.countで1行毎に実際に入力された文字数と比較、差分
を"△"で埋めて、レコ-ドに格納する(そうすれば、呼び出した時は、入力時のままで再現できると考えていました…スペ−ス埋めは再現時ではなく、保存
時の事でした  書き方が下手で誤解させてしまいました)

⇒しかしながら、全角・半角を考慮していなかったので止めました

編集 削除