HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0305
百合子エクセルのデータ読込と書き込みについて教えてください31解決


百合子

リンク

2018/3/5(Mon) 13:55:11|NO.82632

エクセルのデータ読込と書き込みについて教えてください。
データ1を読み込んで、データ2に書き込みたいのですが
やり方がよくわかりません。

データ1は
番号 番号2 1 2 3 平均
1 1 19.9 36.4 38.3 31.5
2 4 15.5 16.9 15.4 16.0
3 5 25.2 38.1 24.8 29.4
4 6 39.0 39.6 11.2 29.9
5 7 26.4 24.7 13.8 21.6
6 8 17.0 31.1 15.5 21.2
7 9 23.6 13.8 20.6 19.4
8 11 27.7 30.0 22.9 26.9
9 12 27.4 12.8 13.4 17.9
10 13 16.7 10.4 32.1 19.7
11 14 15.9 27.6 36.6 26.7
12 15 16.6 28.3 18.9 21.3
13 18 26.4 11.9 36.4 24.9
14 19 38.6 27.9 32.0 32.8
15 20 12.2 34.3 38.8 28.4
16 21 18.9 14.0 33.3 22.1
17 22 18.9 19.7 17.1 18.6
18 25 36.4 19.3 27.8 27.8
19 26 17.7 35.8 12.6 22.0
20 27 13.4 20.3 31.2 21.6
21
22
23
24
25

このような形で、番号2・1・2・3・平均を読み込み、
データ3の指定したセルに(番号1のデータは番号2をC1、1・2・3・平均をC3,C4,C5,C6に
番号2のデータは番号2をP1、1・2・3・平均をP3,P4,P5,P6になどデータのある分指定箇所に)
書き込みたいです。

またデータ1のデータ(番号の数)は数はだいたい20個くらいなのですが、
違うときもあるのでデータのある分だけ読み込めたりできるでしょうか?

教えて頂ける方いらっしゃいましたら、よろしくお願いします。



この記事に返信する


あまら

リンク

2018/3/5(Mon) 19:15:40|NO.82633

Excelデータというのは、○○○.xls などのファイルという事でしょうか?

この形式のファイルを読み書きする事も出来るんですが
かなり複雑なソースになるので理解は難しいかもしれません。

少々手間がかかりますが、簡単な方法としては
一旦ファイルをCSV形式で保存し、HSPでCSVファイルを読み込み、
やりたい処理をした上でCSVで保存。
HSPで作ったCSVをExcelで読み込むというCSVを間に挟む形での処理なら
比較的簡単に理解できると思いますよ。



さか

リンク

2018/3/5(Mon) 22:34:01|NO.82635

少し前に同じような質問がありました。
以下が参考になるのではと思います。

http://hsp.tv/play/pforum.php?mode=all&num=82038



百合子

リンク

2018/3/5(Mon) 23:03:38|NO.82636

あまらさん是非その方法で教えていただけないでしょうか。



あまら

リンク

2018/3/6(Tue) 01:58:01|NO.82638

CSV利用のサンプルソースを作るのは構わないのですが、いくつか不明な箇所があります。

> データ3の指定したセルに(番号1のデータは番号2をC1、1・2・3・平均をC3,C4,C5,C6に
> 番号2のデータは番号2をP1、1・2・3・平均をP3,P4,P5,P6になどデータのある分指定箇所に)
> 書き込みたいです。
すみませんが、言葉だけではどういう処理をしたいのかがよくわかりません。

【データ3の指定したセル】とは?
> データ1を読み込んで、データ2に書き込みたい
と最初に書かれていますが、データ3とはどこから出てきたのでしょうか。

【番号1のデータ】とはデータ1ファイルの「番号の列」の事でしょうか?

> 番号2をC1、1・2・3・平均をC3,C4,C5,C6に
> 番号2のデータは番号2をP1、、1・2・3・平均をP3,P4,P5,P6に
とありますが、同じデータをそれぞれC列とP列の2つの場所に書き込みたいということでしょうか?

このように一体何をしたいのかがよくわかりません。
データ1の内容を書き込んだように
データ2の内容をこういう形にしたいと詳しく書き込んで下さると
わかりやすくなります。
可能ならば処理前と後の例をスクリーンショット画像として
アップロードしてもらえるといいかもしれません。



そして平均の値ですが、例として平均の最初にあたる「セルでいうF2の 31.5 」の箇所は
ただの数値ならばいいのですが、
もしかして関数(『=AVERAGE(C2,D2,E2)』 とか 『=(C2+D2+E2)/3』 など)を
使用しているのでしょうか?
だとするとCSVでやるのは少々面倒かもしれません。

この辺りを明確にして下さると詳しく説明することができます。



百合子

リンク

2018/3/6(Tue) 15:02:28|NO.82639

さかさんありがとうございます、参考にさせて頂きます。



百合子

リンク

2018/3/6(Tue) 15:41:20|NO.82640

あまらさん
文章がおかしくてすみません。

> データ2の指定したセルに(番号1のデータは番号2をC1、1・2・3・平均をC3,C4,C5,C6に
> 番号2のデータは番号2をP1、1・2・3・平均をP3,P4,P5,P6になどデータのある分指定箇所に)
> 書き込みたいです。
すみませんが、言葉だけではどういう処理をしたいのかがよくわかりません。

もともとのエクセルファイル・データ1(読み込みたいファイル)
番号1,番号2,no1,no2,no3,平均
1,1,19.9,36.4,38.3,31.5
2,4,15.5,16.9,15.4,16.0





20,27,13.4,20.3,31.2,21.6


データ2(書き込みたいファイルイメージ)
うまく説明できればいいのですが、
例えばデータ1の2行目の1,1,19.9,36.4,38.3,31.5の各数字を好きなところに書き込めるように
してみたいです。
1はA2,1はB2,19.9はF2,36.4はG2,38.3はH2,31.5はI2などです。
2行目以降も
2はA3,4はB3,15.5はF3,16.9はG3,15.4はH3,16.0はI3など
データ1にある行数分読み込んで書き込みたいです。

また書き込む位置は任意の場所に指定したいです。(好きな場所)


【データ3の指定したセル】とは?
> データ1を読み込んで、データ2に書き込みたい
と最初に書かれていますが、データ3とはどこから出てきたのでしょうか。
すみませんデータ3は× → データ2を書き間違えてしまいました。

【番号1のデータ】とはデータ1ファイルの「番号の列」の事でしょうか?
はいその通りです。

> 番号2をC1、1・2・3・平均をC3,C4,C5,C6に
> 番号2のデータは番号2をP1、、1・2・3・平均をP3,P4,P5,P6に
とありますが、同じデータをそれぞれC列とP列の2つの場所に書き込みたいということでしょうか?
すみませんこれも間違えてしまい、番号2と番号3でした。
番号2を3行目に書き込み、次の番号3を16行目に書き込み、その次は番号4を・・・
番号の数値を13行とばしに書き込みたいと思っていました。

平均の計算はエクセルで『=AVERAGE(C2,D2,E2)』を 使ってしまっています。

私の説明に間違いや下手でごめんなさい、
あとアップロードというのもどうやるかわかりません、
いろいろ教えてほしいです、お願いします。



あまら

リンク

2018/3/6(Tue) 19:33:02|NO.82643

>また書き込む位置は任意の場所に指定したいです。(好きな場所)
おおよそわかりましたが、任意の場所ですか…
ちょっと時間がかかりそうです。


あと追加で確認させてください。

関数等の計算を使っている箇所は平均だけでしょうか?

現在私のPCにExcelを入れていないため確認できないのですが、
CSVの読み込みや保存の際に区切り記号を設定できるでしょうか?

LibreOfficeは入れているので、
これだと読み込み時に文字コードや区切り記号の設定が可能ですし、
保存の際にも文字コード・区切り記号・計算結果の代わりにセルの数式を保存
という設定が可能なんですが、Excelはそういう細かい所は設定できたでしょうか。


一度下記のデータをtest.csvとしてメモ帳などで保存して
エクセルで読み込んでみてください。

test.csv
A1になる,B1になる,C1になる
A2になる,B2になる,C2になる A3になる,B3になる,C3になる



あまら

リンク

2018/3/6(Tue) 19:49:37|NO.82644

すみません
何故か変な所に改行が入っていますね。
test.csvの空行は削除してから保存してみてください。



リンク

2018/3/6(Tue) 20:37:48|NO.82646

 こんばんは、横からすみません。

 ExcelでのCSV形式の扱いについてです。
 なお、これは2013以降で確認しており、2007とか2003ではどうなっているのか、手元に該当のプログラムがないので、わからないです。

 まず、読み込みに関して

 関連付けから読み込んだ場合は、基本的に、タブで区切られたテキストであれば、きちんと読み込んでくれます。
 ただ、コンマやその他の文字で区切られたテキストだとうまく読み込んでくれません。
 なお、Excelの「ファイルを開く」から外套のファイルを指定して読み込んだ場合は、区切り文字等を設定するウィザードが表示されます。

 続いて、保存に関して。

 Excelでの保存の際は、「名前を付けて保存」のダイアログの「ファイルの種類」で「CSV(コンマ区切り)」もしくは「テキストファイル」という形式を指定する必要があります。
 この際、「テキストファイル」として保存した場合は、タブ区切りのテキストとして保存されるようです。
 なので、コンマで区切られたデータで保存したい場合は「CSV」を選んでください。
 なお、保存する際にファイルの種類に「UTF-8」とか「Unicode」などとついてる形式で保存すると、ユニコードで保存されてしまうので、HSPで読み込むことを想定するのであれば、注意する必要があります。
 なお、Excel2013だとタブ区切りだけでしか保存できなかったかもしれません。
 実機がないので、今確認できないのが申し訳ないです。

 以上、参考になれば幸いです。



あまら

リンク

2018/3/6(Tue) 21:02:36|NO.82647

陸さん情報提供ありがとうございます。

タブ区切りが使えるなら関数があっても大丈夫そうですね。
コンマは関数内にも入っているので、
そこで区切られると面倒なことになってしまいますので。



リンク

2018/3/6(Tue) 22:46:30|NO.82649

 こんばんは。

 Excel2016で試してみました。
 ExcelでCSV形式で保存した場合、関数は計算結果が保存されるようです。

 それでは。



あまら

リンク

2018/3/6(Tue) 23:37:24|NO.82652

> ExcelでCSV形式で保存した場合、関数は計算結果が保存されるようです。
ああ、やはり式ではなく結果の数値になってしまいますか。


バージョンによって多少違うでしょうが、区切り記号や計算式の出力について調べてみました。

まず、公式の説明ではコントロールパネルの設定で
CSVの区切り記号を変更できるようです。
https://support.office.com/ja-jp/article/%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB-txt-%E3%81%BE%E3%81%9F%E3%81%AF-csv-%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%BE%E3%81%9F%E3%81%AF%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88-5250ac4c-663c-47ce-937b-339e391393ba

この区切り記号が、どこまで設定されるのかわからないので
無難に「テキスト(タブ区切り)」でtxtファイルにする方が良さそうですね。

そして計算式の出力に関しては、こちらで解説されていました。
http://mokichi7.blog.fc2.com/blog-entry-105.html



あまら

リンク

2018/3/7(Wed) 00:19:20|NO.82655

エラーチェック等まったく無しの手抜きだらけのソースですが
一応これで出来ると思います。

前提条件としてExcelでの読み書きはどちらも
タブ区切りでShift-JISのファイルとしてください。

平均の計算式は元のデータに関係なく、ソースで平均の計算式を作るようにしました。

行の数字や列のアルファベットに適当な数字・アルファベットを入れてみてください。
右上の「関数の更新」ボタンクリックで関数のセル値が変更した行・列に合わせて変更されます。

必ず「関数の更新」をしてから「CSV保存」してください。


列のアルファベットに数字や記号を入れるとたぶん不具合が起こります。
行の数字の所も半角数字以外を入れると同様に不具合になりそうです。

一番右のアルファベットを最終列、一番下の行を最終行として処理するので
列は通常のエクセルと同じで左から順にアルファベット順で
行は上から順に大きな数(一番下が一番大きな数)にしてください。

// 各変数等の初期化 #const TAB 0x09 // タブ文字コード #const CEL 100 // セルに含まれる最大文字数(Excelでは 32,767らしいけど今回はそんなに使わない) #const IPTW 80 // 入力ボックス幅 #const IPTH 20 // 入力ボックス高さ filename1 = "データ1.csv"; // 読み込むファイル名 filename2 = "データ2.csv"; // 保存するファイル名 data1c = 0; // データ1の列数 data1r = 0; // データ1の行数 screen 0, 800, 600, 0; #module // 数値をアルファベットに変換 #defcfunc NumToA int p01 rcstr = ""; // 1文字目はAを0 2文字目以上はAを1と考える if( (p01 / 676) == 0 ) { if( (p01 / 26) == 0 ) { // アルファベット1文字 poke rcstr, 0, p01+0x41; poke rcstr, 1, 0; } else { // アルファベット2文字 poke rcstr, 0, p01/26+0x40; poke rcstr, 1, p01\26+0x41; poke rcstr, 2, 0; } } else { // アルファベット3文字 poke rcstr, 0, p01/676+0x40; poke rcstr, 1, (p01\676)/26+0x40; poke rcstr, 2, (p01\676)\26+0x41; poke rcstr, 3, 0; } return rcstr; // アルファベットを数値に変換 #defcfunc AToNum str s01 len = strlen(s01); s02 = s01; if( len == 3 ) { // アルファベット3文字の場合 rcint = (peek(s02, 0)-0x40)*676 + (peek(s02, 1)-0x40)*26 + (peek(s02, 2)-0x41); } else:if( len == 2 ) { // アルファベット1文字の場合 rcint = (peek(s02, 0)-0x40)*26 + (peek(s02, 1)-0x41); } else { // アルファベット1文字の場合 rcint = peek(s02, 0)-0x41; } return rcint; // 小文字を大文字へ変換 #defcfunc aToA str s01 len = strlen(s01); rcstr = s01; repeat len w = peek(rcstr, cnt); if( (0x61 <= w) && (w <= 0x7A) ) { poke rcstr, cnt, w-0x20; } loop return rcstr; #global // データ1ファイルの読み込み sdim csvdata1, 64; // 読み込み時に自動で容量確保されるため数字は適当 notesel csvdata1; noteload filename1; data1r = notemax; // 行数取得 // 列数取得処理 sdim data0, 64; noteget data0, 0; // 0行目取得 idxmax = strlen(data0); repeat idxmax // 0行目に含まれるタブの数を数える(タブ数+1が列数になる) p01 = peek(data0, cnt); if( p01 == TAB ) { data1c++; } loop data1c++; // 最後に+1が列数になる // データ1ファイルの内容をセル単位で変数に書き込む sdim data1, CEL, data1c, data1r; // data1(列, 行)の順 repeat data1r sdim data0, 64; // 一応変数初期化 noteget data0, cnt; // 行取得 cnt1 = cnt; idx = 0; repeat data1c getstr data1(cnt, cnt1), data0, idx, TAB; idx += strsize; loop loop // オブジェクト配置 objsize IPTW, IPTH; dim objidr, data1r; // 行数分 dim rnums, data1r; dim objidc, data1c; // 列数分 sdim cnums, data1c; // 行(数字の入力ボックス) pos 0, IPTH; repeat data1r rnums(cnt) = cnt+1; input rnums(cnt); objidr(cnt) = stat; loop // 列(アルファベットの入力ボックス) repeat data1c pos IPTW*(cnt+1), 0; cnums(cnt) = NumToA(cnt); input cnums(cnt); objidc(cnt) = stat; loop pos 700, 0; button gosub "関数の更新", *replace; pos 700, 40; button gosub "CSV保存", *save; gosub *print_data; stop; *print_data // データ表示 color 255, 255, 255:boxf; color 0, 0, 0; repeat data1r y = (cnt+1)*IPTH; cnt1 = cnt; repeat data1c x = (cnt+1)*IPTW; pos x, y; mes data1(cnt, cnt1); loop loop return; *replace // ついでに列のアルファベットを全て大文字に変換 repeat data1c cnums(cnt) = aToA(cnums(cnt)); objprm objidc(cnt), cnums(cnt); loop // 関数の整形 repeat data1r // 1文字目が=ならば関数と判断する if( peek(data1(5, cnt), 0) == '=' ) { cel01 = ""+cnums(2)+""+rnums(cnt)+""; // AVERAGE関数 セル1つ目 cel02 = ""+cnums(3)+""+rnums(cnt)+""; // AVERAGE関数 セル2つ目 cel03 = ""+cnums(4)+""+rnums(cnt)+""; // AVERAGE関数 セル3つ目 data1(5, cnt) = "=AVERAGE("+cel01+","+cel02+","+cel03+")"; } loop gosub *print_data; return; *save // CSV保存処理 col = AToNum(cnums(data1c-1))+1; // 平均の列を一番右端とする row = rnums(data1r-1); // 一番下の行を最終行とする sdim data2, CEL, col, row; // 保存用データ // 最初に全てを区切り記号(タブ)にする repeat row cnt1 = cnt; repeat col data2(cnt, cnt1) = "\t"; loop loop // 1行ずつデータを格納する repeat data1r cnt1 = cnt; r = rnums(cnt)-1; repeat data1c c = AToNum(cnums(cnt)); data2(c, r) = data1(cnt, cnt1); if( (cnt+1) != data1c ) { // 行末でなければ区切り記号(タブ)を追加 data2(c, r) += "\t"; } loop loop // 保存用CSVデータ作成 csvdata2 = ""; notesel csvdata2; repeat row data0 = ""; cnt1 = cnt; repeat col data0 += data2(cnt, cnt1); loop noteadd data0, cnt; loop notesave filename2; dialog ""+filename2+"に保存しました。", 0, "CSV出力"; return;

毎回、行・列を入力するのが面倒ならば
(変な所に改行が入らなければ)

123行目の rnums(cnt) = cnt+1;
131行目の cnums(cnt) = NumToA(cnt);

がそれぞれ行と列の初期値ですから、
これを消してrepeatの前に何らかの方法で初期値を設定してください。

予想以上に長くなってしまいましたが、
これでもExcelファイルを直接読み書きするよりはマシだと思います。



あまら

リンク

2018/3/7(Wed) 00:36:20|NO.82656

すみません、うそつきました。

>平均の計算式は元のデータに関係なく、ソースで平均の計算式を作るようにしました。
最初の文字が「=」だと計算式と判断するようにソースを組んでいたので、
NO.82652の計算式の出力を参考に、平均の列は数値ではなく式にしてください。



百合子

リンク

2018/3/7(Wed) 10:17:07|NO.82659

あまらさんありがとうございます。感動です。
それにいろいろ調べていただいて本当にありがとうございます。
私もこんなコードを書けるようになりたいです。



百合子

リンク

2018/3/7(Wed) 13:34:13|NO.82662

あまらさんすみません
列のアルファベットですが変えてみても
位置が変えられません。
いろいろやってもらってばかりで申し訳ありませんが、
教えてもらえないでしょうか?



あまら

リンク

2018/3/7(Wed) 14:25:54|NO.82663

うーん、LibreOfficeだと区切り文字だけでも列として扱ってくれるんですが
Excelだと空のフィールドは無視されるんでしょうか。

保存処理の所だけ修正し、空のフィールド(セル)には""を入れるようにしました。
これでどうでしょうか?

*save // CSV保存処理 col = AToNum(cnums(data1c-1))+1; // 平均の列を一番右端とする row = rnums(data1r-1); // 一番下の行を最終行とする sdim data2, CEL, col, row; // 保存用データ // 最初に全てをダブルクォーテーション+区切り記号(タブ)にする repeat row cnt1 = cnt; repeat col if( (cnt+1) == col ) { // 行末には区切り文字を入れない data2(cnt, cnt1) = "\"\""; } else { data2(cnt, cnt1) = "\"\"\t"; } loop loop // 1行ずつデータを格納する repeat data1r cnt1 = cnt; r = rnums(cnt)-1; repeat data1c c = AToNum(cnums(cnt)); if( data1(cnt, cnt1) == "" ) { // 空データはダブルクォーテーションを入れておく data1(cnt, cnt1) = "\"\""; } data2(c, r) = data1(cnt, cnt1); if( (cnt+1) != data1c ) { // 行末でなければ区切り記号(タブ)を追加 data2(c, r) += "\t"; } loop loop // 保存用CSVデータ作成 csvdata2 = ""; notesel csvdata2; repeat row data0 = ""; cnt1 = cnt; repeat col data0 += data2(cnt, cnt1); loop noteadd data0, cnt; loop notesave filename2; dialog ""+filename2+"に保存しました。", 0, "CSV出力"; return;



あまら

リンク

2018/3/7(Wed) 22:08:37|NO.82668

再修正です。

元データに空セルがあったら『""を元データに入れる』という所を
元データに空セルがあったら『""を保存データに入れる』としました。


説明不足でしたが『""』というのは空のセルがあるという事を示すだけで、
Excelで読み込んだ時には何も表示しないはずです。

*save // CSV保存処理 col = AToNum(cnums(data1c-1))+1; // 平均の列を一番右端とする row = rnums(data1r-1); // 一番下の行を最終行とする sdim data2, CEL, col, row; // 保存用データ // 最初に全てをダブルクォーテーション+区切り記号(タブ)にする repeat row cnt1 = cnt; repeat col if( (cnt+1) == col ) { data2(cnt, cnt1) = "\"\""; } else { data2(cnt, cnt1) = "\"\"\t"; } loop loop // 1行ずつデータを格納する repeat data1r cnt1 = cnt; r = rnums(cnt)-1; repeat data1c c = AToNum(cnums(cnt)); if( data1(cnt, cnt1) == "" ) { // 空データはダブルクォーテーションを入れておく data2(c, r) = "\"\""; } else { data2(c, r) = data1(cnt, cnt1); } if( (cnt+1) != data1c ) { // 行末でなければ区切り記号(タブ)を追加 data2(c, r) += "\t"; } loop loop // 保存用CSVデータ作成 csvdata2 = ""; notesel csvdata2; repeat row data0 = ""; cnt1 = cnt; repeat col data0 += data2(cnt, cnt1); loop noteadd data0, cnt; loop notesave filename2; dialog ""+filename2+"に保存しました。", 0, "CSV出力"; return;



百合子

リンク

2018/3/8(Thu) 10:24:58|NO.82670

あまらさん何度もありがとうございます。
なんどもごめんなさいなのですが、
実行したときに行の入力ボックスは行の数出るのですが
列の入力ボックスは1つしかでないみたいで、
例えば最初Aが出ているのをCに変えて"関数の更新"をしたのですが、
結果が変わりませんでした。
行のほうは指定した好きなところにでるようになってました。

何度もすみませんが、教えてもらえないでしょうか?



あまら

リンク

2018/3/8(Thu) 10:40:58|NO.82672

実行時に読み込んだファイルの内容を最初の一行(公開しても問題のない行)だけでもいいので
ここにコピー&ペーストしてもらえますか?

メモ帳なんかのテキストエディタで開けるはずです。

列が1つということはソース的に考えるとタブが無い=タブ区切りになっていない。
という状況のはずです。

行は改行で判定されるので問題なかったのでしょうね。
たぶん区切り文字が別の文字になっているのが問題なんだと思います。



百合子

リンク

2018/3/8(Thu) 10:57:37|NO.82673

あまらさん

実際に読み込んだデータ1.csvです。(テキストで開いてみたものです)


番号 番号2
1 1 74.1 73.5 71 =AVERAGE()
2 4 68.1 67.6 69.6 =AVERAGE()
3 5 70.7 72.5 69.1 =AVERAGE()
4 6 71.7 72.7 73.2 =AVERAGE()
5 7 67.7 65.4 68 =AVERAGE()
6 9 72.7 74.5 71.1 =AVERAGE()
7 11 66.9 64.3 66.1 =AVERAGE()
8 12 66.8 64.6 64.4 =AVERAGE()
9 13 71.1 70.5 73.2 =AVERAGE()
10 14 68.8 65.3 66.1 =AVERAGE()
11 15 67.8 69.6 65.5 =AVERAGE()
12 18 67 68.1 70.1 =AVERAGE()
13 19 73.2 74 70.3 =AVERAGE()
14 20 67 68.6 67 =AVERAGE()
15 21 67.8 65.9 67.7 =AVERAGE()
16 22 72.7 70.6 71.4 =AVERAGE()
17 25 67 66.6 70.1 =AVERAGE()
18 27 70.8 70.3 68.8 =AVERAGE()
19 28 67.8 70.4 68.7 =AVERAGE()
20
21
22
23
24
25

それとあまらさんが使われているLibreOfficeのcalcというのを使ってみましたら
しっかりとできました。
エクセルとはちがうものなのでしょうか?



百合子

リンク

2018/3/8(Thu) 11:04:52|NO.82674

あまらさんまたお願いになってしまうのですが、
行のように列も1列目と2列目に間をとるようなことはできるでしょうか?
データ1 1列目、2列目、3列目・・・
データ2 1列目、2列目(空白の列)、3列目(データ1の2列目)、4列目(データ1の3列目)・・・

いろんなことを聞いてしまいすみません。



あまら

リンク

2018/3/8(Thu) 11:35:10|NO.82675

あれ…ちゃんとタブ区切りになっていますね
タブのコードが違うんでしょうか?
バイナリエディタでそのファイルのタブの位置の文字コードを見るとわかるかもしれませんが、
すみませんがExcelで出力されたファイルをこちらで細かく確認できないのでわかりません。

LibreOfficeは元々オープンソースで
Officeと同じようなことが出来るソフトを目指して開発されてきた物なので
見た目や動作が非常に似ていますが、

Officeにあるようなこれは別に要らないだろうという機能が削られていたり、
逆にこういうことも出来たらいいのにという機能が追加されていたり、
(今回で言うとCSVで読み書きするときに区切り文字を好きに選べるように)
微妙に違う所も結構あります。



>行のように列も1列目と2列目に間をとるようなことはできるでしょうか?
それは可能なはずです。
空いている列は保存するときに、""【タブ】となり
何もデータがない列が入ります。
LibreOfficeではありますが何度か確認したので
間違いなく空の列が入りました。



百合子

リンク

2018/3/8(Thu) 13:49:32|NO.82676

あまらさん、説明がへたですみません。

「行のように列も1列目と2列目に間をとるようなことはできるでしょうか?」
あまらさんに作ってもらったコードで実行画面上でA列はA列、B列をはC列みたいな指定が
出来るようになったりしますか?

データ1(読み込みファイル)
A B C D E
番号 番号2
1 1 74.1 73.5 71 =AVERAGE()
2 4 68.1 67.6 69.6 =AVERAGE()
3 5 70.7 72.5 69.1 =AVERAGE()




データ2(書き込みファイル)
A B C D E F
番 空白 号 番号2
1 空白 1 74.1 73.5 71 =AVERAGE()
2 空白  4 68.1 67.6 69.6 =AVERAGE()
3 空白  5 70.7 72.5 69.1 =AVERAGE()



出力するときにAはそのままでBを空白にして C,D,E,Fに書くような感じです。

できるでしょうか?



あまら

リンク

2018/3/8(Thu) 14:32:27|NO.82677

こちらも説明が悪かったですね。

>あまらさんに作ってもらったコードで実行画面上でA列はA列、B列をはC列みたいな指定が
>出来るようになったりしますか?
なっていますよ。

少しデータで気になる所がありますが
実行画面での列の初期値は
『A B C D E F』
となっているかと思います

そこを例えば
『A C G H I J』
として更新&保存すると
飛ばした列『B D E F』は空白して保存されているはずです。


以下気になる所
>データ1(読み込みファイル)
>番号 番号2
となっていますが、
最初の行で何列あるのか(最初の行のタブの数+1が列数)を数えているので
番号 番号2 平均
として6列全てに何らかの文字を入れた方が確実に列が数えられるかもしれません。

もしくは
ソースの88行目
noteget data0, 0; // 0行目取得
この箇所を

noteget data0, 1; // 1行目取得
として1行目(最初から2番目の行)の方で列数を数える方式に変更してください。



>データ2(書き込みファイル)
>A B C D E F
>番 空白 号 番号2
『番 空白 号』これはミスですよね?
一ヶ所だけのセルの分割みたいな事までは
さすがにご自分でやっていただきたいです(^^;



あまら

リンク

2018/3/8(Thu) 14:45:30|NO.82678

追記

>実行画面での列の初期値は
>『A B C D E F』
>となっているかと思います

>そこを例えば
>『A C G H I J』
>として更新&保存すると
>飛ばした列『B D E F』は空白して保存されているはずです。

A列はA列のまま
B列はC列に
同様にC、D、E、F列はG、H、I、J列として移動され保存されます。



百合子

リンク

2018/3/8(Thu) 16:54:12|NO.82679

あまらさん何度も何度もすみません。

>実行画面での列の初期値は
>『A B C D E F』

実行画面でなぜかAしか出てきません。あと#error7 in line 172と出てきてしまいました。
平均の=AVERAGE()の文字が悪いのでしょうか?
エクセルからcvsに変えるとき平均が数字にもなるようなので、
文字でなく数値で行う場合は簡単に変えられるでしょうか?
その部分らしいところを消したりしたのですが、
うまくいきませんでした。



百合子

リンク

2018/3/8(Thu) 17:08:50|NO.82680

あまらさん
今csvをtxt(タブ区切り)に変えてみたら、しっかり実行できました。



あまら

リンク

2018/3/8(Thu) 17:28:20|NO.82681

あーやっぱりタブでなくコンマ区切りになっていましたか。


後は一応補足として

Aしか出て来ないということは、列が1つしかないということで
タブがカウントされていませんね。
たぶんコンマ区切りとか別の区切り記号ファイルになってしまっているのでしょう。

6列目(F列のこと)を固定で平均値関数だという前提で更新しているので
Aしかないというので、たぶん配列変数の参照エラーになってしまっているのだと思われます。
172行目の data1(5, cnt) が、読み込んだデータのF列(5)の任意の行(cnt)を
参照という意味です。



>平均の=AVERAGE()の文字が悪いのでしょうか?
ここで見ているのは最初の「=」だけなので
その後がどんな文字だろうが数字だろうが記号だろうが関係ありません。
むしろ「=」だけでもAVERAGE関数とみなして更新時に
自動で =AVERAGE(C2,D2,E2) などに書き換えます。
別の計算式でもAVERAGEになってしまうので、そこは注意してください。



あまら

リンク

2018/3/8(Thu) 17:47:14|NO.82682

最初にソースをのせたときとその前で テキスト(タブ区切り)で〜
と軽く書いていたんですが、ソース内のファイル名などがcsvになっていたせいで
色々と混乱させてしまったようですね。

一応修正版全ソースをのせておきます。
filenameは好きなように変えてください。

// 各変数等の初期化 #const TAB 0x09 // タブ文字コード #const CEL 100 // セルに含まれる最大文字数(Excelでは 32,767らしいけど今回はそんなに使わない) #const IPTW 80 // 入力ボックス幅 #const IPTH 20 // 入力ボックス高さ filename1 = "タブ区切りのCSVとかTXTのファイル名"; // 読み込むファイル名 filename2 = "保存するときのファイル名"; // 保存するファイル名 data1c = 0; // データ1の列数 data1r = 0; // データ1の行数 screen 0, 800, 600, 0; #module // 数値をアルファベットに変換 #defcfunc NumToA int p01 rcstr = ""; // 1文字目はAを0 2文字目以上はAを1と考える if( (p01 / 676) == 0 ) { if( (p01 / 26) == 0 ) { // アルファベット1文字 poke rcstr, 0, p01+0x41; poke rcstr, 1, 0; } else { // アルファベット2文字 poke rcstr, 0, p01/26+0x40; poke rcstr, 1, p01\26+0x41; poke rcstr, 2, 0; } } else { // アルファベット3文字 poke rcstr, 0, p01/676+0x40; poke rcstr, 1, (p01\676)/26+0x40; poke rcstr, 2, (p01\676)\26+0x41; poke rcstr, 3, 0; } return rcstr; // アルファベットを数値に変換 #defcfunc AToNum str s01 len = strlen(s01); s02 = s01; if( len == 3 ) { // アルファベット3文字の場合 rcint = (peek(s02, 0)-0x40)*676 + (peek(s02, 1)-0x40)*26 + (peek(s02, 2)-0x41); } else:if( len == 2 ) { // アルファベット1文字の場合 rcint = (peek(s02, 0)-0x40)*26 + (peek(s02, 1)-0x41); } else { // アルファベット1文字の場合 rcint = peek(s02, 0)-0x41; } return rcint; // 小文字を大文字へ変換 #defcfunc aToA str s01 len = strlen(s01); rcstr = s01; repeat len w = peek(rcstr, cnt); if( (0x61 <= w) && (w <= 0x7A) ) { poke rcstr, cnt, w-0x20; } loop return rcstr; #global // データ1ファイルの読み込み sdim csvdata1, 64; // 読み込み時に自動で容量確保されるため数字は適当 notesel csvdata1; noteload filename1; data1r = notemax; // 行数取得 // 列数取得処理 sdim data0, 64; noteget data0, 0; // 0行目取得 idxmax = strlen(data0); repeat idxmax // 0行目に含まれるタブの数を数える(タブ数+1が列数になる) p01 = peek(data0, cnt); if( p01 == TAB ) { data1c++; } loop data1c++; // 最後に+1が列数になる // データ1ファイルの内容をセル単位で変数に書き込む sdim data1, CEL, data1c, data1r; // data1(列, 行)の順 repeat data1r sdim data0, 64; // 一応変数初期化 noteget data0, cnt; // 行取得 cnt1 = cnt; idx = 0; repeat data1c getstr data1(cnt, cnt1), data0, idx, TAB; idx += strsize; loop loop // オブジェクト配置 objsize IPTW, IPTH; dim objidr, data1r; // 行数分 dim rnums, data1r; dim objidc, data1c; // 列数分 sdim cnums, data1c; // 行(数字の入力ボックス) pos 0, IPTH; repeat data1r rnums(cnt) = cnt+1; input rnums(cnt); objidr(cnt) = stat; loop // 列(アルファベットの入力ボックス) repeat data1c pos IPTW*(cnt+1), 0; cnums(cnt) = NumToA(cnt); input cnums(cnt); objidc(cnt) = stat; loop pos 700, 0; button gosub "関数の更新", *replace; pos 700, 40; button gosub "CSV保存", *save; gosub *print_data; stop; *print_data // データ表示 color 255, 255, 255:boxf; color 0, 0, 0; repeat data1r y = (cnt+1)*IPTH; cnt1 = cnt; repeat data1c x = (cnt+1)*IPTW; pos x, y; mes data1(cnt, cnt1); loop loop return; *replace // ついでに列のアルファベットを全て大文字に変換 repeat data1c cnums(cnt) = aToA(cnums(cnt)); objprm objidc(cnt), cnums(cnt); loop // 関数の整形 repeat data1r // 1文字目が=ならば関数と判断する if( peek(data1(5, cnt), 0) == '=' ) { cel01 = ""+cnums(2)+""+rnums(cnt)+""; // AVERAGE関数 セル1つ目 cel02 = ""+cnums(3)+""+rnums(cnt)+""; // AVERAGE関数 セル2つ目 cel03 = ""+cnums(4)+""+rnums(cnt)+""; // AVERAGE関数 セル3つ目 data1(5, cnt) = "=AVERAGE("+cel01+","+cel02+","+cel03+")"; } loop gosub *print_data; return; *save // CSV保存処理 col = AToNum(cnums(data1c-1))+1; // 平均の列を一番右端とする row = rnums(data1r-1); // 一番下の行を最終行とする sdim data2, CEL, col, row; // 保存用データ // 最初に全てをダブルクォーテーション+区切り記号(タブ)にする repeat row cnt1 = cnt; repeat col if( (cnt+1) == col ) { data2(cnt, cnt1) = "\"\""; } else { data2(cnt, cnt1) = "\"\"\t"; } loop loop // 1行ずつデータを格納する repeat data1r cnt1 = cnt; r = rnums(cnt)-1; repeat data1c c = AToNum(cnums(cnt)); if( data1(cnt, cnt1) == "" ) { // 空データはダブルクォーテーションを入れておく data2(c, r) = "\"\""; } else { data2(c, r) = data1(cnt, cnt1); } if( (cnt+1) != data1c ) { // 行末でなければ区切り記号(タブ)を追加 data2(c, r) += "\t"; } loop loop // 保存用CSVデータ作成 csvdata2 = ""; notesel csvdata2; repeat row data0 = ""; cnt1 = cnt; repeat col data0 += data2(cnt, cnt1); loop noteadd data0, cnt; loop notesave filename2; dialog ""+filename2+"に保存しました。", 0, "ファイル出力"; return;



百合子

リンク

2018/3/8(Thu) 19:04:51|NO.82683

あまらさんできました。
いろいろ本当にありがとうございました。
私もこんなコードができるように勉強がんばります。



ONION software Copyright 1997-2021(c) All rights reserved.