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

解決


アンブレラ  2010-09-08 09:38:18  No: 39108

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

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

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

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

おねがいします


HOta  2010-09-08 17:52:22  No: 39109

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

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


茶柱  2010-09-08 20:54:03  No: 39110

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

(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 21:37:44  No: 39111

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

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-09 08:36:39  No: 39112

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

あと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 14:54:53  No: 39113

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

先ずは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 19:41:18  No: 39114

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

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

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


ぽむぽむ  2010-09-10 20:46:39  No: 39115

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

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


Delphi大好き  2010-09-10 20:51:27  No: 39116

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

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

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

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

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

参考になれば幸いです。


アンブレラ  2010-09-14 07:17:07  No: 39117

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

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

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

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

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

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

---


TS  2010-09-14 08:34:24  No: 39118

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


Quest  2010-09-14 09:49:58  No: 39119

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


Delphi大好き  2010-09-14 18:45:59  No: 39120

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

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

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


Delphi大好き  2010-09-14 21:18:53  No: 39121

以下で試したらきちんとメモ帳に改行されて表示できました。
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 19:33:14  No: 39122

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


アンブレラ  2010-09-15 20:06:58  No: 39123

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

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

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

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

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


アンブレラ  2010-09-15 20:30:29  No: 39124

HOta さんのご指摘へ

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

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

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


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

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






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