アプリ版:「スタンプのみでお礼する」機能のリリースについて

英単語について文字ごとに点数を設定し、その単語が何点になるか計算する関数を作ろうとしています。以下の通り書いたのですが、セルを指定しても=wscore("apple")と指定しても、Loadingと表示された後エラーどころか何の反応も返ってこないままセルが真っ白です。どうしてでしょうか?
ちなみにデバッグすると8行目でtoLowerCase()が呼び出せないといわれます。しかし対処法がわかりません。
よろしくお願いいたします。

function wscore(w){
var i;
var s;
var wd;
var ws;

//入力文字列を大文字に変換
wd = w.toLowerCase();

//文字数(ループ回数)を取得
for (i=1;i<=wd.length;i++){

//i番目の文字を取得
ws = wd.substring(i,1);

//点数を検索
switch (ws){
case "a", "e", "i", "l", "n", "o", "r", "s", "t", "u":
s = 1;
case "d", "g":
s = 2;
case "b", "c", "m", "p":
s = 3;
case "f", "h", "t", "v", "w":
s = 4;
case "k":
s = 5;
case "j", "x":
s = 8;
case "q", "z":
s = 10;
}

//得点に足す
wscore = wscore + s;

//次の処理へ
}
}
以上

A 回答 (7件)

No6です



>上図のR2セルに=hoge(B2)と入れてみたところ、stringと表示されました。
おやっ! ちゃんと文字列が引数に代入されているようですね・・・?
エラーメッセージのundefinedはなんだったんだろうか・・・

>デバッグの段階ではwには何も入っていない状態なのでundefinedになるということでしょうか。
えっ! 実行環境でデバッグしてはいないってことですか?
引数を与えずに関数を実行してみたってこと??
それで、undefinedのエラーが出てたってことでしょうか!?
(それなら、そうなりますよねぇ…)
実行時のエラーだとばかり、てっきり勘違いをしていました。(大変、失礼いたしました)

ようやく理解できて来たようです。(遅くてすみません)
もし上記の状態であるなら、ご提示のコードの問題点を修正するだけで(多分)機能するのではないかと思います。

試みに、ご提示のものとほぼ同様の内容で、簡易的に作成してみました。
一度、試してみてください。
※ 元のコードでは、switch~case で場合分けしていますがまとめて配列で処理しています。
※ アルファベットのA~Z、a~z以外の文字は、スコアの対象としません。
 (ご提示のコードでは「y」の得点がないので、yも無得点扱いにしてあります)
※ 引数が文字列以外の場合は、""を返します。
 (対象セルに未だ文字が入力されていない場合等に、0表示にならない意味も含めています)
※ 変数名等はかなりいい加減なので、設定し直した方が良いかも。

function hoge(v){
if (typeof(v) != "string" || v.length == 0) return "";
const val = [1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,,10];

let t = 0, vL = v.toLowerCase();
for(let i=0, c; c = vL.charCodeAt(i++);){
t += val[c - 97]?val[c - 97]:0;
}
return t;
}
    • good
    • 0
この回答へのお礼

お礼が遅くなり申し訳ありません。
お手本になるコード、書いていただきありがとうございました。これを基に勉強すすめてゆこうと思います。
今回JavaもGASも初めて触れましたが、fujilinさんのおかげでよい出会いとなりました。初心者に辛抱強くお付き合いいただいたこと、改めてお礼申し上げます。

お礼日時:2019/08/01 05:40

No5です



>wからwdを取り出す必要があるということですね?
かなり違います。

No4の回答以降は、「関数の問題以前に呼び出し側にも問題があるのでは?」と書いています。
(だから、関数には問題が無いというわけではなく、いろいろとありますが…)
とは言え、引数がundefinedで渡されているという確証がないので、まずは、それを確認してみてはいかがという意味です。
No1の回答からずっと「引数(=w)を調べてみては?」と申し上げていますが、そのままの内容です。

もしも、確認がとれたととするなら、
>wからwdを取り出す必要があるということですね?
いくら関数側で何をしようとも、値を取得することはできないでしょう。
なぜなら、必要な情報(=引数)が渡されていないからです。

ですので、「それよりも前」に問題がありそうと申し上げているのですが、その部分に関しては情報も無く、仕様も知らないので、私にはわかりかねますという意味です。
    • good
    • 1
この回答へのお礼

基本的なところが理解できていないようで、ご迷惑をおかけします。

引数を調べてみる、方法が思いつかず、せっかくのご助言も生かせないでいます。

すでにお分かりとは思いますが、やろうとしていることは以下の通りです。これがそれよりも前の情報にあたればよいのですが…
1. ブラウザ上のGoogleスプレッドシートに英単語をリスト化します。この英単語は将来追加されます。
2. 英単語をもとに点数を計算するユーザー定義関数(wscore)をGoogleAppsScriptを用いて作成し、セルに書きこみます。たとえば新しい英単語がB10セルに追加されると=wscore(B10)を自動計算して値を表示します。
https://imgur.com/5YTmp5G
こういった画面です。Q列にはExcelVBAで作った同様の動作をするユーザー定義関数で得た数値を値のみ貼り付けています。これをGoogleスプレッドシートだけで実現したくて試み、現在非常にお世話になっているという次第です。

ご教示いただいたhogeで上図のR2セルに=hoge(B2)と入れてみたところ、stringと表示されました。

デバッグの段階ではwには何も入っていない状態なのでundefinedになるということでしょうか。
ひとまず以下の文を4行目に足した時、=wscore()と呼び出すと0を返すようになりましたし、デバッグしても引っかかることはなくなりました。
if (w == null){return 0;}

しかし=wscore("apple")だったり、=wscore(B2)の場合は#NUM!エラーを返してきます。

右も左もわからぬ状態で、お手数をおかけします。

お礼日時:2019/07/23 21:45

No4です



>ユーザー定義関数のような引数が入るスクリプトはデバッグができない~
なぜそのようなことになるのかわかりません。
No2のお礼にご提示の画像は、多分エディタだと思いますが、見たところ、簡単なデバッグ機能が付属しているように思われますが、そうではないのでしょうか?

何度もお断りしますが、私はAppsScriptは存じませんので、ユーザ関数の呼び出しや、戻り値のセット方法がどのような仕組みがどのようになっているのか知りません。
再三書いているように、受け取った引数を調べれば問題の箇所を絞り込むことが可能と思います。
(No3のお礼からすでに、undefinedらしいことはうかがえますが…)
また、このようなステップをデバッグの一環とはお考えではないのでしょうか?

例えば、
function hoge(v){
return v===null?"null":v===""?"blanc":!isNaN(v)?"number":typeof(v);
}
などとしておいて、hogeを呼出せば、渡された引数の大雑把なタイプ分けが返されます。
もしも、こちらでもundefinedが返されるようなら、引数の内容がundefinedになっていることになるので、ご質問文に示された「ユーザ定義関数の内容」の問題ではなく、それ以前の「シートでのユーザ関数の設定方法」の問題になるものと思います。
この場合は、シート側の仕様がどうなっているのかをよくご確認ください。

まずは、それに適合した使用法をしない限りは、関数の利用はできないものと思いますので・・・
    • good
    • 1
この回答へのお礼

たびたびありがとうございます。

>引数の大雑把なタイプ分けが返されます。
つまり引数を文字列であるかセルであるかを判別してwからwdを取り出す必要があるということですね?ネタ元のVBAではそこは全く考えないでやってましたので、思いつきませんでした。

>デバッグ云々
こちらも私の勘違いです。スクリプトの編集はお察しのとおりGoogleのscript.google.comで提供されているエディタですが、VBAのエディタではほぼ同じ場所に「コンパイル」があって、これと混同して考えてました。お恥ずかしい限りです。

ひとまず、wの内容について分岐させる文を入れようと思います。結果は後程報告させていただきます。何はともあれ、ありがとうございました。

お礼日時:2019/07/23 15:34

No3です。



>「TypeError: undefinedのメソッド「toLowerCase」を呼び出せません。
ようやく、原因のヒントが少しは得られてきたようです。
引数がundefinedと評価されているということなので、質問文にご提示の関数ではなく、それ以前に、呼出し側で引数の内容がセット出来ていないことが疑われます。
これ以上は、全く情報が記されていないのでこちらではわかりかねます。

>返却値について書きこまなければいけないようなので~
それに関しても気にはなっていましたが、ご質問のエラーとは直接関係が無さそうなので、ひとまずスルーしていました。

No2にも書きましたが、私はAppsScriptを存じませんので、仕様はわかりませんが……
>wscore = wscore + s;
これって、functionを上書きしてしまっていませんか?
(処理内容としても怪しげな内容になっていますけれど・・)
普通に考えると、特殊なケースでもない限りは行わないことのように思います。
また、AppsScriptにおけるユーザ関数の戻り値は、returnで戻す仕様ではないのでしょうか?

……などなど、正しい仕様に合わせた関数にしておかないと、なかなか意図する結果は得られないものと思います。
    • good
    • 1
この回答へのお礼

たびたびありがとうございます。

>呼出し側で引数の内容がセット出来ていないことが疑われます。
となるとユーザー定義関数のような引数が入るスクリプトはデバッグができない、ということなんでしょうか。

>ご質問のエラーとは直接関係が無さそうなので、
ひとまず、return文を足したら(まったく意図したものとは違いますが)結果が返ってくるので、「うんともすんとも」に関しては解決ですね。それが意図したものになることが新たに出てきた問題ですが。

>wscore = wscore + s; これって、functionを上書きしてしまっていませんか?
wscoreの内容にsを足す、という処理のつもりだったんですが、Javascriptでは通用しないんですね。文字数分ループしてi番目の文字のポイントを評価し、それをwscoreに足してゆき、最終的にそれが戻り値になる、という処理をさせたいんですが、どう書いたらよいのでしょう?

すみません、急がないのでお休みは休んでくださいね。お時間のあるときによろしくお願いします。

お礼日時:2019/07/20 19:03

No2です



>wは上記の例では"apple"やご指摘の通りRangeにあたるものです。
"apple"は文字列ですが、RangeはObjectでしょうから同じには扱えないでしょう。

>エラーですが、メッセージが秒速で消えるので、~~
エラーメッセージがどこにあるのかわかりませんが、下の方の変数欄を右に見ていくと(多分、内容が表示されているのではないかと想像)、wはundefinedになっていませんか?
どのタイミングで、どのようなスコープによる参照なのかわからないので、実行時にもundefinedとは限らないのかも知れませんが、undefined.toLowerCase() でも、当然エラーが発生するでしょう。

毎回書いていますように、wのタイプが何で、内容がどうなっているかを確認するのが先ではないでしょうか?
    • good
    • 1
この回答へのお礼

理解の悪いものに長々とお付き合い、ありがとうございます。Javaはこの件で初めて触れましたので、非常に心強いです。

スプレッドシート上でwscore(A1)のようにセルを引数にすることと、wscore("apple")のように文字列を引数にすることとは別途に考えて書く必要がある、ということですか?難しいですねー。
スクショとってみたら、「TypeError: undefinedのメソッド「toLowerCase」を呼び出せません。(行8、ファイル「コード」)となってました。

またほかのサイトを見たりなどして、返却値について書きこまなければいけないようなので、for文を抜けた後ろに「return wscore;」と追加し、スプレッドシート上で=wscore("apple")と実行したところセルに次の戻り値がありました。
"
function wscore(w) {
var i;
(文字制限により中略)
ws = wd.substring(i, 1);
switch (ws) {
case ""a"", ""e"", ""i"", ""l"", ""n"", ""o"", ""r"", ""s"", ""t"", ""u"":
s = 1;
case ""d"", ""g"":
s = 2;
case ""b"", ""c"", ""m"", ""p"":
s = 3;
case ""f"", ""h"", ""t"", ""v"", ""w"":
s = 4;
case ""k"":
s = 5;
case ""j"", ""x"":
s = 8;
case ""q"", ""z"":
s = 10;
}
wscore = wscore + s;
}
return wscore;
}
undefined10101010"

うー、どうしたらいいんだろう。

お礼日時:2019/07/20 10:22

No1です。



AppsScriptは知りませんので、はっきりとはわかりませんが・・・

>wはスプレッドシートから引数として渡してくるので、~
何が渡されるかは、スクリプト側で制御しているのではないのですか?
(いきなり渡されることはないでしょうから、何らかの要求をしているはずです)
もしも、不定のものが渡されてくるような状況であるなら、受け取った時点でのチェックは不可欠と思いますが、実際はそのようなことはなくて、引数の内容は決まっているのではないのでしょうか?

根拠のないまったくの想像ですが、エクセルで言うところの「Rangeオブジェクト」になっていそうな気がしますが、そんなことはありませんか?


>これが文字列であることを予め設定しておくことができるんでしょうか?
そのような機能は(多分)ないと思います。
関数を再定義して事前にチェックするような処理を加えれば、見かけ上はそのような機能を作成することは可能だと思います。
とは言っても、結局のところ、その内部で以下と同じような処理を行うことになるのではないでしょうか。

通常は、受け取った側で内容をチェックして、想定外の内容の場合は
 ・無視する(=何もしない) とか
 ・エラー表示する      とか
 ・実際にエラーを発生させる
などの処理を行うのではないでしょうか?

いずれにしろ、typeof w でwの種類がわかるのではないかと思いますので、チェックしてみるのが宜しいかと。あるいは、エラーメッセージに書いてあったりしませんか?
    • good
    • 1
この回答へのお礼

早速ありがとうございます。大変心強いです。

ユーザー定義関数として使い、wscore("apple")ならばa(1)+p(3)+p(3)+l(1)+e(1)なので9が返るように、これがそれぞれのセルについて評価するようにしたいんです。B2セルに入っているのがorangeなら7とか。基本的に英単語しか入っていないので、エラー処理は特段してません。

文字列であるところを改めて云々はVBAで書いている「w As String」などの書き方です。
Public Function Wscore(w As String) As Integer
wは上記の例では"apple"やご指摘の通りRangeにあたるものです。...何も入ってないときは初期値を入れるような処理が必要でしょうかね。

エラーですが、メッセージが秒速で消えるので、確認しづらいんです。画面はこんなです。
https://imgur.com/xP47c7l

重ね重ねありがとうございます。

お礼日時:2019/07/19 12:17

こんにちは



>デバッグすると8行目でtoLowerCase()が呼び出せないといわれます。
単純に、wが文字列ではないのでは?
wの内容を確認してみるか、エラーメッセージをよく読むと、もう少し情報が増えるのではないでしょうか?
    • good
    • 1
この回答へのお礼

ありがとうございます。Java/GASは初めてでして、挙動がわからず戸惑っております。
https://oshiete.goo.ne.jp/qa/11214123.html
VBAで作ったこの内容をGoogleスプレッドシートに当てはめようとしています。wはスプレッドシートから引数として渡してくるので、コンパイル時点では何も入ってないんですが、これが文字列であることを予め設定しておくことができるんでしょうか?

お礼日時:2019/07/19 09:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!