「Web出版サイト」ベータ公開

Q&A集[?]

当サイトでのご質問の受付は終了しました

すべてのコンテンツを読み込み専用としたため、回答欄からも投稿できません

Apache OpenOffice/LibreOfficeのご質問はそれぞれのフォーラムへご投稿ください

質問コーナー

サイト内検索

分類メニュー

関連サイト


本日:1
昨日:2
総数:6233
現在:6


文字長

ページOpenOffice.org FAQの登録ページ
投稿者まくまくま
分類
edit/refer
優先順位
edit/refer
状態
edit/refer
カテゴリー
edit/refer
投稿日2008-06-16 15:14:41 (月)
OSWindows 2k
依存するページ
バージョン
edit/refer

メッセージ

回答ページでは行末に「~」を付加する必要はありません

文字長「LEN」は動作するのですが、 「LENB」でバイト長が動作しません。

バイト長を知るための方法はないでしょうか?


LENBはありません

M.Kamataki (2008-06-16 15:31:03 (月))

カテゴリーは「Calc 表計算」で良いでしょうか。であれば、CalcにはLENB関数がないので動作しません。

回避方法などは調査中です。もしわかる方がいらっしゃれば、コメントお願いします。

Issueはありました

M.Kamataki (2008-06-16 15:56:52 (月))

OpenOffice.orgに関する要望・不具合を登録するデータベースIssueTrackerには以下の項目が挙がっていました。LENB関数のリクエストです。4年間動きがないので「3.0ベータで確認して欲しい」という機械的なコメントが付いています。

Problem recognizing some functions :
http://ja.openoffice.org/issues/show_bug.cgi?id=11073

どのようなことをご希望でしょうか。

Tora (2008-06-16 21:39:31 (月))

Len() 関数は、文字数を返しますよね。「あいう」であれば 3。
Excel 日本語版の Lenb では、「あいう」の場合、6 かな。
Excel 英語版では、Lenb は動作するのだろうか。そもそもあるのだろうか。

実は、日本語などの文字は、UTF-8 という文字コードだと一文字あたり 3 バイト。UCS-2, SJIS, EUC-JP, Code Page 932 などの文字コードだと 2 バイト、JIS だと、、、、う〜ん、Escape In , Escape Out などの余計な制御コードが前後につくから、いっぱいバイト。

というわけで、言い訳がましいのですが、、、Lenb なる関数は、21世紀の Unicode を中心として開発されている OpenOffice.org では、その仕様を決めにくいので、実現できそうにもないかと。思います。

Lenb ではなく、Len_for_Windows_Japanese() みたいな、Windows 日本語版上で動作する Excel 日本語版の動作と同じ振る舞いをする関数ね。っていう特注品を開発するのであれば、できますが、、、、それでは、互換性が成り立ちませんよね。あぁ、どうしましょうか。。。

ところで、つまるところ、バイト数を調べて、どのようなことを行いたいのでしょうか。多分、なにかしらの代替手段があるかとは思いますので。

補足

Tora (2008-06-16 21:49:33 (月))

OpenOffice.org では、内部処理で、俗に言う半角文字は、2バイト。俗に言う全角文字も 2バイト。割り当てて処理が行われています。JIS第何水準などの最近追加されてきた文字には、4バイト。割り当てているんじゃないかな。

というわけで、強引に Lenb を実装すると、半角文字 3文字、例えば abc に対して 6 を返すようになってしまいますです。

って、実際に作るなら、そんなことにならないように、逆の意味での回避策を入れめばいいんですけど。

すみません。言い訳ばかりで。

蛇足

ponkan (2008-06-17 13:04:50 (火))

文字コードの意味を理解出来ていないと戸惑うかも知れないですね。
一昔前の98機とかで苦労した時代もありました。
万国共通にとUnicodeが成長しているので、今後はこの扱いに慣れるのが良いと思います。

実装についての指標を、例によって文章で書いて見ます。
‖仂殃源列を一文字ずつ読み込み
半角文字であるかないかを判定し、半角は1全角は2を返す
J源列の終わりまで繰り返し合計する。

味噌は半角を判定する事、それは絶対数が少ないからですが・・・
文字列{ABCDE・・・abcde・・・123・・・+/etc}と対照を取れば良い。
OOobasicではinstr関数でしょうか?
まぁ、一文字ずつでなくても良さそうですが。

ponkan (2008-06-17 17:46:03 (火))

文字コードを理解していないと、本当は間違うようにも思うが
昔の言葉で言うところの、日本語での1バイト文字とか2バイト文字とか限定だと
こんな感じにはなる。(半角カナは省いてある)

function test76(tes)                                   rem 文字列の長さを測ってみたりした
yt = "ABCDEFGHIJKLMNOPQRSTUWXYZ ""abcdefghijklmnopqrstuwxyz+-*/~^.,:;@1234567890!#$%&'(){}`=\[]<>?_"
cou1 = len(tes)                                        rem 文字数を数えてみる
for i = 1 to cou1
hantei = left(tes,1)                                   rem 一文字を取出す
if instr(yt,hantei) <> 0 then tanicho = 1 : goto ER1
tanicho = 2
ER1:
Mid(tes,1,1,"")                                        rem 判定終了文字を削る
nagasa = nagasa + tanicho
next i
test76 = nagasa
end function


世界は広いので3バイト文字とかもあるのだが、なにせ文字コードが・・・
何に使いたいのかが判らないとなんとも言えないが、まぁ適当に直せば使えるかも知れない。
カテゴリがインストールなんで、要領を得ない話ではありますが。

ponkan版LENB

M.Kamataki (2008-06-19 09:01:00 (木))

試してみました。英数字+テキストなどでもバイト長で表示されます。質問されたまくまくまさんはどうでしょうか。

なるほど、では、似通った方法ですけど。

Tora (2008-06-20 19:42:16 (金))

マクロを使って、LENB という関数を自作してみるという方法です。

Function LENB(s)
	Dim i, n, m
	n = 0
	m = len(s)
	For i = 1 to m
		If (Asc(Mid(s, i, 1)) < 256) Then
			n = n + 1 ' 半角文字の場合
		Else
 			n = n + 2 ' それ以外の場合
		End If
	Next i
	LENB = n
End Function


バイト数をコンピューターとして計測しているのではなく、単に、半角文字なら 1、それ以外なら 2 として、一文字ずつ調べて、加算していくだけのプログラムです。

いや、だから文字コードが・・・

ponkan (2008-06-20 21:07:27 (金))

American Standard Chord だから・・
環境依存型とか、如何にも訳わからない世界に嵌りそうなんで
まぁ取敢えず、動けばok。

ありがとうございます。

まくまくま (2008-06-24 09:06:25 (火))

データをCALで入力してもらった物をデータベースに取り込もうと思っていました。
データベースに文字数の制限があるので、Excelで調べていまいした。
入力時にバイト数がわかると、編集しながら調整できるので便利だと思っていました。

マクロでできるようですが、マクロの使用方法がよくわかりません。
先ずはマクロを覚えようと思います。

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

そのデータベースで使う文字コードの種別を調べてみるのもよいかと思います。

Tora (2008-06-24 12:25:34 (火))

最近のデータベースでは、文字列型のデータの文字コードを明示的に指定できるようになっていると思います。

文字コードとしては、
(a) 欧米の文字を主に使う。  日本では半角文字と呼ばれることが多い文字。
(b) アジアの文字を主に使う。 日本では全角文字と呼ばれることが多い文字です。

Windows は、2000 以降、内部でユニコードを使っているようです。しかしながら、98 などの昔の版との互換性のために、データベースとの通信やファイルへの保存のために、わざわざ、コードページ923(俗にシフトJISと呼ばれるものに近い)に文字コード変換を掛けるなど内部で行っているようです。

Excel, Access, OpenOffice.org, MySQL, ... Windows 2000以降のWindows、など、すべて、ユニコードを使えるようになっています。

というわけで、2008 年においては、いまさら、Windows 98 時代に使われていた文字コードに、アプリケーション間通信時などに、変換作業を差し込むようなことは、(事実上性能上の問題などにはまったくならないとは思いますが)、無駄な作業といえるのではないかと思います。

データベースに文字数の制限があるので、Excelで調べていまいした。


とともに、そのデータベースの文字列型の文字コードの指定方法や使用できる文字コードについても調べておくとよいかと思います。

そして、必要のない文字コード変換作業が発生しないような設定にすることが、性能上、良いのではないかと思います。

半角文字のみしか含まれないフィールドには、欧米文字系の文字コードを。
全角文字が含まれる可能性のあるフィールドには、ユニコードなどの文字コードを。
設定できるように、設定するように、しておくことができるのではないかと思います。

(背景として、日本語の文字コード、韓国語の文字コード、インドの文字コード、などなど、すべての文字コードで動作するようにプログラムに工夫を施すとか、さまざまな文字コードでその開発したプログラムが問題なく動作することをテストする作業とか、いまさら、やってられなくなってきた。国際的に統一した文字コードであるユニコードについては完璧にサポートします。他の国別や地域別の文字コードについては、たぶんうまく動くとは思いますよ。というような雰囲気になりつつあるのではないかと思います。ですので、いまさら、シフトJIS のような文字コードを使うというのは、あまり得策ではないかと思います。)

今日は、我が身に降りかかる。

ponkan (2008-07-02 09:41:09 (水))

calcデータを他のAPのデータに変換している。
あちらは、VC++開発らしいがデータのフォーマットが変だぜ〜
固定長のはずなのに、所々byteが抜けている・・・(口が裂けないと不具合とは云えないし)
byte単位で書込するのかよ・・・byte?
ありゃ?、文字列要素が固定byteだぜ〜・・・とか。しくしく

これから先が・・・長いんだろうなぁ

ponkan (2008-07-02 17:55:20 (水))

時間が無かったので、toraさんのLENBを拝借してみたが
やっぱり半角カナで(ど壷)に嵌ったりした。

真面目に半角カナも書いてみた

function test76(m)
t = "abcdefghijklmnopqrstuwxyz ""_+-*/~^.,:;@1234567890!#$%&'(){}`=\[]<>?"
t = t + "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョー"
t = t + "ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ"
for i = 1 to len(m)
l = l + iif(cbool(instr(t,mid(lcase(m),i,1))),1,2)
next i
test76 = l
end function


ついでに、文字列を指定byte長にするものも作ってみた

function test77(s,k) rem 文字列を指定byte長にする s:対象文字列 k:指定byte長
m = len(s) : n = test76(s)-k                       '無理矢理test76を使う
if n > 0 then s = left(s,m-1) : test77(s,k)        '再帰処理の動作保障は無い
if n < 0 then s = s + String$(abs(n),Chr$(&H20))   '穴埋め文字も議論の対象かも
test77 = s
end function

無題

ponkan (2008-07-03 09:14:01 (木))

判定文字列の中に[v]が抜かってました・・m(__)m
他にもあるかも知れません、自爆しています。

wc;strlen()

(2008-07-03 18:08:28 (木))

単に、wcコマンド、あるいは、strlen()関数(C)を使えばよいでしょう。
欲しいのは、バイト長なのですから。

無題

ponkan (2008-07-03 19:36:43 (木))

御高説は承りました。
wcコマンド、或いはstrlen()関数(C)の実装方法を教えて頂けますか?

まぁ、ピュアなoOo.basicが好きなのですが。

javaのlength()か?

(2008-07-04 11:00:43 (金))

Cのstrlen()でもよいのですが、OOoとの連携を考えると、
JAVAのlength()がよいように思えます(バイト長を返すとあります)。
残念ながら、私はOOoのマクロとして組み込むやりかたを知りません。
でも、ここには、ご存じの方がたくさんいらっしゃると思います。

一方、wcコマンドは、OSのコマンドなので、OOoとは関係がありませんが、
文字長だけを知りたいのであれば、これが一番簡単です。
wc.exeをインストールするだけです。あるいは、すでに用意されている
かもしれません。

半角文字についても、考慮するようにしてみました。

Tora (2008-07-04 17:47:08 (金))

Function LENB(s)

	' Print ">" & s & "<" ' 渡されてくる内容を表示して確認する
	
	If IsNumeric(s) And s = 0 Then ' 空欄のセルの場合、数値 0 が渡されてくるみたいです。
		' 数値 0 のセルと空欄のセルで区別がつきませんが、とりあえず、値 0 を返しましょう。
		LENB = 0 ' 値 0 を返す
		Exit Function
	End If

	Dim i, n, m, c
	n = 0
	m = len(s)

	For i = 1 to m
		c = Asc(Mid(s, i, 1)

		Select Case c

			' http://www.unicode.org/charts/PDF/U0000.pdf
			' http://www.unicode.org/charts/PDF/U0080.pdf
			Case 0 To 255
				n = n + 1 ' 半角英数字文字の場合

			' http://www.unicode.org/charts/PDF/UFF00.pdf
			' http://www.unicode.org/Public/UNIDATA/UnicodeData.txt の
			' FF61;HALFWIDTH IDEOGRAPHIC FULL STOP から
			' FF9F;HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK まで
			Case 65377 To 65439 
				n = n + 1 ' 半角カナ文字の場合

			Case Else
	 			n = n + 2 ' それ以外の場合
		End Select
	Next i

	LENB = n
End Function


文字コード変換という基本的な機能は、OpenOffice.org に備わっているのですが、うまい表現ではありませんが、あまりにも基本的な機能であるため、BASICのような高度なプログラミング言語からその基本的な機能を簡単には使えないようです。

例えば、出力先の文字コードを指定してファイル等へ文字列などを書き出す機能があります。その文字コードとして Windows 98 日本語版の頃使われていた俗に言うシフトJISコードを変換先文字コードとして出力させることは簡単にできるようです。が、そのような方法では、一秒間に数百回処理するのがやっとではないかと思います。つまり、1000個の情報をその方法で処理しようとしたら10秒待たされる。というような換算になります。ですので、一回限り手入力時のチェックなどに使うのであれば、使えますが、より一般的な処理にそのような方法を使うのは、やはり現実的とはいえません。その他にも、ファイルへ書き出すのではなく読み取るストリームへ接続してパイプという方法でそのパイプに文字コード変換を掛けながら書き込み、そのパイプの反対側からバイトコードとして読み出すというような方法も考えられますが、その方法ですと、他のプロセスなどとの通信で使うのであればよいのですが、自身で書き込み自身で読み出そうとすると、デッドロック状態に陥ってフリーズしたような状態に陥る可能性もありまして。というのは、パイプに何か書き込みがなされるまで、読み出そうと試みてはいけないわけです。なぜなら、読み出せるまでずっと待ってしまうからです。また、大量に書き込んでしまうと、反対側で読み出してくれるまで、書き込みが途中で止まって待ってしまうような状態に陥ったりする可能性があります。

とまぁ、考えてみて、最初に戻りますが、なぜに、この2008年になって、1990年代の文字コードと戦われているのでしょうか。そこのそもそもの部分をすっきりとさせるとか、そもそも、そのシステムそのものを最初から作り直すとか、まったく別の解決法を探したほうが、今後のことも考えると、よいのではないかなぁとも思います。数年先もそのシステムを使いつづけるべきか否か。と。

無題

ponkan (2008-07-04 17:56:28 (金))

何か勘違いをされているようなので、コメント入れておきます。

正直申しますと、私のプラットホーム(OS)はwinなのですが
oOo.basicに於いてはWIN32APIの殆どの関数は呼出可能で、私自身は既に呼出定義済みです。
この事はWIN32APIに限らず、その他のAPIに関しても情報さえ入手出来れば自前で呼出定義し
実装・利用可能であろうと推察されるかと思います。(早い話がdll呼出の事)

問題はその関数のプラットホーム・ロケール、若しくはディストリビューションの違いにあります。
所謂、環境依存型関数でありハードウェア・言語・OS等の様々な環境により動作が保障されない
という事だろうと思います。

自然な形のbasicのままで、希望とする所の動作(バイト長に限らず)を達成する事ができれば
少なくともそれは、OOoという環境の上では動作する事が可能であるはずです。
詰まる所、WindowsだろうがLinuxだろうが、OOoがインストールされている環境であれば
動作するようなものを求めている・・という事です。

OOo以外のアプリケーション(例えば裏帳簿作成ソフトとか)を仕事に使っている人達が
そのデータファイルを、OOoで参照・編集できるようになれば
OOoも使ってくれるようになるかも知れない・・・とか思ったりするのです。
(まぁ大概は、DBがらみをbaseかcalcで・・ですが)

因みにですが、このbasicはインタープリタなのでインクルードとか出来ません・・?
それを差し引いても相応に優秀な言語だと、私は思っています。
ジャバァとかパイソ〜ンとか猫ビンとかは論外という事で、お願いします。
いや、別に他意は無いのですが。
私のooO_240には見当たらないので・・・追放した覚えも無いのだけどなぁ。

無題

ponkan (2008-07-04 18:18:31 (金))

ありゃ
推敲している間にToraさんのコメントを頂いていたようで、有難う御座います。

Ascは固定なので私は今後は使わない予定です。
それよりも判定文字列を自身で定義し、別の関数への応用を持たせるのが
私には有意義だと感じるからです。
それにしても、言語のロケールは奥が深いものがあるようです。

半角英数字と半角カナの文字列

Tora (2008-07-05 20:45:05 (土))

Linux 上で、半角英数字と半角カナの文字を機械的に作ってみました。

perl -e 'for $c (0x20 .. 0x7e) { print chr($c) }; print "\n"' > halfwidth_letters_UTF-8.txt
perl -e 'for $c (0xa1 .. 0xdf) { print chr($c) }; print "\n"' | iconv -f CP932 -t UTF-8 >> halfwidth_letters_UTF-8.txt

halfwidth_letters_UTF-8.txt

Tora (2008-07-05 20:48:44 (土))

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚

無題

tani (2010-04-21 14:07:35 (水))

こんなの作ってみました。
シート上の数式で使う関数としてなら充分なんじゃないかなーと思います。(処理速度とか気にしてませんが。)
もちろん文字コードとか気にしないタダの文字列処理ですので本気のバイナリ処理とかは無理です。

Option Explicit

Function LenB(oPara) As Integer
 Dim retrun As Integer
 Dim tmp_str As String
 Dim s As String
 Dim i As Integer
 Dim oTextSearch As Object
 Dim aOptions As Object
 Dim aResult As Object

 retrun = 0
 tmp_str = ""

 On Error Resume Next
 tmp_str = Cstr(oPara)
 On Error Goto 0

 If tmp_str = "" Or tmp_str = "0" Then
   LenB = retrun
   Exit Function
 End If
 
 oTextSearch = CreateUnoService("com.sun.star.util.TextSearch")
 aOptions = CreateUnoStruct("com.sun.star.util.SearchOptions")
 aOptions.algorithmType = com.sun.star.util.SearchAlgorithms.REGEXP
 aOptions.searchFlag = com.sun.star.util.SearchFlags.REG_EXTENDED
 aOptions.searchString = "^[ -~。-゚]*$" ' 半角のみかどうか
 oTextSearch.setOptions(aOptions)

 For i = 0 To Len(tmp_str) - 1
   s = Mid(tmp_str, i+1, 1)
   aResult = oTextSearch.searchForward(s, 0, 0)
   
   If aResult.subRegExpressions <> 1 Then
     retrun = retrun + 2
   Else 
     retrun = retrun + 1
   End If
 Next i

 LenB = retrun
End Function


Function MidB(oPara1, oPara2, oPara3) As String
 Dim retrun As String
 Dim tmp_str As String
 Dim s As String
 Dim i As Integer
 Dim oTextSearch As Object
 Dim aOptions As Object
 Dim aResult As Object
 Dim istart As Integer
 Dim iend As Integer
 Dim iCount As Integer

 retrun = ""
 tmp_str = ""
 iCount = 0

 On Error Resume Next
 tmp_str = CStr(oPara1)
 istart = CInt(oPara2)
 iend = CInt(oPara3)
 On Error Goto 0

 If tmp_str = "" Or tmp_str = "0" Or iend <= 0 Or istart <=0 Then
   MidB = retrun
   Exit Function
 End If
  
 oTextSearch = CreateUnoService("com.sun.star.util.TextSearch")
 aOptions = CreateUnoStruct("com.sun.star.util.SearchOptions")
 aOptions.algorithmType = com.sun.star.util.SearchAlgorithms.REGEXP
 aOptions.searchFlag = com.sun.star.util.SearchFlags.REG_EXTENDED
 aOptions.searchString = "^[ -~。-゚]*$" ' 半角のみかどうか
 oTextSearch.setOptions(aOptions)

 For i = 0 To Len(tmp_str) - 1
   s = Mid(tmp_str, i+1, 1)
   aResult = oTextSearch.searchForward(s, 0, 0)
    
   If aResult.subRegExpressions <> 1 Then
     iCount = iCount + 2
     If iCount = istart Then
       s = " "
     End If
     If iCount = iStart + iend Then
       retrun = retrun & " "
     End If
   Else 
     iCount = iCount + 1
   End If
   
   If iCount >= istart AND iCount < istart + iend Then
     retrun = retrun & s 
   End If
 Next i

 MidB = retrun
End Function

無題

tani (2010-04-21 14:11:03 (水))

ちなみに半角カナの「バ」とか「パ」を2文字として計算しちゃいますが、Excelのシート上のLenB関数とかMidB関数とかも、「バ」とか「パ」を2文字として計算するので、まぁいいかな、と思います。
MidBで中途半端なところを区切ってしまった時の挙動も、Excelのシート上のMidBと同じように半角スペースで埋めるようにしてます。

お名前:
題名:


添付ファイル: filehalfwidth_letters_UTF-8.odt 1040件 [詳細] filehalfwidth_letters_UTF-8.txt 818件 [詳細]