Excel セルの罫線の報告
本家チケット 3044
no information about the cell border is given in an Excel sheet, if the cell border is different from the adjacent cells.
https://github.com/nvaccess/nvda/issues/3044
メモ:
メモ:
XlBordersIndex Enumeration https://msdn.microsoft.com/en-us/library/office/ff835915.aspx
XlLineStyle Enumeration https://msdn.microsoft.com/en-us/library/office/ff821622.aspx
手元の作業ファイルでは罫線を説明できる目処が立ったが、 まず英語でどのように文章化する仕様がよいのか、 それを適切に日本語化できるためにはどういうローカライズの実装がよいのか。。
以下は NVDAObjects/window/excel.py で formatField を設定して、speech.py でログ出力だけさせてみた例。 上下左右に実線がある。
INFO - speech.getFormatFieldSpeech (21:59:06): at the bottom edge continuous line at the left edge continuous line at the right edge continuous line at the top edge continuous line
ここまでの作業(本家 master からの diff ):
diff --git a/source/NVDAObjects/window/excel.py b/source/NVDAObjects/window/excel.py index a3794c1..ad53488 100755 --- a/source/NVDAObjects/window/excel.py +++ b/source/NVDAObjects/window/excel.py @@ -195,6 +195,55 @@ backgroundPatternLabels={ # Translators: A type of background pattern in Microsoft Excel. xlPatternRectangularGradient:_("rectangular gradient"), } +# XlBordersIndex Enumeration +# see https://msdn.microsoft.com/en-us/library/office/ff835915.aspx +xlDiagonalDown = 5 +xlDiagonalUp = 6 +xlEdgeBottom = 9 +xlEdgeLeft = 7 +xlEdgeRight = 10 +xlEdgeTop = 8 +xlInsideHorizontal = 12 +xlInsideVertical = 11 +bordersIndexLabels={ + # Translators: borders index in Microsoft Excel. + xlDiagonalDown:_("from upper left to lower right"), + # Translators: borders index in Microsoft Excel. + xlDiagonalUp:_("from lower left to upper right"), + # Translators: borders index in Microsoft Excel. + xlEdgeBottom:_("at the bottom edge"), + # Translators: borders index in Microsoft Excel. + xlEdgeLeft:_("at the left edge"), + # Translators: borders index in Microsoft Excel. + xlEdgeRight:_("at the right edge"), + # Translators: borders index in Microsoft Excel. + xlEdgeTop:_("at the top edge"), + # Translators: borders index in Microsoft Excel. + xlInsideHorizontal:_("horizontal borders except outside"), + # Translators: borders index in Microsoft Excel. + xlInsideVertical:_("vertical borders except outside"), +} +# XlLineStyle Enumeration +# see https://msdn.microsoft.com/en-us/library/office/ff821622.aspx +xlContinuous = 1 +xlDash = -4115 +xlDashDot = 4 +xlDashDotDot = 5 +xlDot = -4118 +xlDouble = -4119 +xlLineStyleNone = -4142 +xlSlantDashDot = 13 +borderStyleLabels={ + # Translators: border styles in Microsoft Excel. + xlContinuous:_("continuous line"), + xlDash:_("dashed line"), + xlDashDot:_("alternating dashes and dots"), + xlDashDotDot:_("dash followed by two dots"), + xlDot:_("dotted line"), + xlDouble:_("double line"), + xlLineStyleNone:_("no line"), + xlSlantDashDot:_("slanted dashes"), +} re_RC=re.compile(r'R(?:\[(\d+)\])?C(?:\[(\d+)\])?') re_absRC=re.compile(r'^R(\d+)C(\d+)(?::R(\d+)C(\d+))?$') @@ -958,6 +1007,20 @@ class ExcelCellTextInfo(NVDAObjectTextInfo): formatField['background-color']=colors.RGB.fromCOLORREF(int(cellObj.interior.color)) except COMError: pass + if formatConfig["reportBorderStyle"]: + try: + bordersObj=cellObj.borders + formatField['border-style'] = '' + if bordersObj[xlEdgeBottom].lineStyle != xlLineStyleNone: + formatField['border-style'] += bordersIndexLabels.get(xlEdgeBottom) + ' ' + borderStyleLabels.get(bordersObj[xlEdgeBottom].lineStyle) + if bordersObj[xlEdgeLeft].lineStyle != xlLineStyleNone: + formatField['border-style'] += ' ' + bordersIndexLabels.get(xlEdgeLeft) + ' ' + borderStyleLabels.get(bordersObj[xlEdgeLeft].lineStyle) + if bordersObj[xlEdgeRight].lineStyle != xlLineStyleNone: + formatField['border-style'] += ' ' + bordersIndexLabels.get(xlEdgeRight) + ' ' + borderStyleLabels.get(bordersObj[xlEdgeRight].lineStyle) + if bordersObj[xlEdgeTop].lineStyle != xlLineStyleNone: + formatField['border-style'] += ' ' + bordersIndexLabels.get(xlEdgeTop) + ' ' + borderStyleLabels.get(bordersObj[xlEdgeTop].lineStyle) + except COMError: + pass return formatField,(self._startOffset,self._endOffset) class ExcelCell(ExcelBase): diff --git a/source/config/__init__.py b/source/config/__init__.py index d7cf7bd..f1fca37 100644 --- a/source/config/__init__.py +++ b/source/config/__init__.py @@ -181,6 +181,7 @@ confspec = ConfigObj(StringIO( reportRevisions = boolean(default=true) reportEmphasis = boolean(default=false) reportColor = boolean(default=False) + reportBorderStyle = boolean(default=True) reportAlignment = boolean(default=false) reportLineSpacing = boolean(default=false) reportStyle = boolean(default=false) diff --git a/source/speech.py b/source/speech.py index c213b05..274759c 100755 --- a/source/speech.py +++ b/source/speech.py @@ -1160,6 +1160,8 @@ def getFormatFieldSpeech(attrs,attrsCache=None,formatConfig=None,unit=None,extra # A style is a collection of formatting settings and depends on the application. text=_("default style") textList.append(text) + if formatConfig["reportBorderStyle"]: + log.info(attrs.get("border-style")) if formatConfig["reportFontName"]: fontFamily=attrs.get("font-family") oldFontFamily=attrsCache.get("font-family") if attrsCache is not None else None
仮に「上下は黒の実線、左右は黒の細線」のように報告させるとすると、
のように優先順位をつけて、まとめて文章化する必要がある。
また、線の色を取得する API が未検証(たぶんできるが)。
英語のメッセージと、gettext のテンプレート、日本語のローカライズ、同時に考えた方がいいかも。。
本家のコードをいじりたくないのでソースを分割した:
#NVDAObjects/window/excelCellBorder.py #A part of NonVisual Desktop Access (NVDA) #Copyright (C) 2016 Takuya Nishimoto #This file is covered by the GNU General Public License. #See the file COPYING for more details. #from comtypes import COMError #from logHandler import log # XlBordersIndex Enumeration # see https://msdn.microsoft.com/en-us/library/office/ff835915.aspx xlDiagonalDown = 5 xlDiagonalUp = 6 xlEdgeBottom = 9 xlEdgeLeft = 7 xlEdgeRight = 10 xlEdgeTop = 8 xlInsideHorizontal = 12 xlInsideVertical = 11 bordersIndexLabels={ # Translators: borders index in Microsoft Excel. xlDiagonalDown:_("from upper left to lower right"), # Translators: borders index in Microsoft Excel. xlDiagonalUp:_("from lower left to upper right"), # Translators: borders index in Microsoft Excel. xlEdgeBottom:_("at the bottom edge"), # Translators: borders index in Microsoft Excel. xlEdgeLeft:_("at the left edge"), # Translators: borders index in Microsoft Excel. xlEdgeRight:_("at the right edge"), # Translators: borders index in Microsoft Excel. xlEdgeTop:_("at the top edge"), # Translators: borders index in Microsoft Excel. xlInsideHorizontal:_("horizontal borders except outside"), # Translators: borders index in Microsoft Excel. xlInsideVertical:_("vertical borders except outside"), } # XlLineStyle Enumeration # see https://msdn.microsoft.com/en-us/library/office/ff821622.aspx xlContinuous = 1 xlDash = -4115 xlDashDot = 4 xlDashDotDot = 5 xlDot = -4118 xlDouble = -4119 xlLineStyleNone = -4142 xlSlantDashDot = 13 borderStyleLabels={ # Translators: border styles in Microsoft Excel. xlContinuous:_("continuous line"), xlDash:_("dashed line"), xlDashDot:_("alternating dashes and dots"), xlDashDotDot:_("dash followed by two dots"), xlDot:_("dotted line"), xlDouble:_("double line"), xlLineStyleNone:_("no line"), xlSlantDashDot:_("slanted dashes"), } def getCellBorderStyleDescription(bordersObj): items=[] for pos in bordersIndexLabels.keys(): if bordersObj[pos].lineStyle != xlLineStyleNone: items.append(_("{style} {position}").format( position=bordersIndexLabels.get(pos), style=borderStyleLabels.get(bordersObj[pos].lineStyle ))) return ', '.join(items)
diff --git a/source/NVDAObjects/window/excel.py b/source/NVDAObjects/window/excel.py index a3794c1..05d7df9 100755 --- a/source/NVDAObjects/window/excel.py +++ b/source/NVDAObjects/window/excel.py @@ -196,6 +196,8 @@ backgroundPatternLabels={ xlPatternRectangularGradient:_("rectangular gradient"), } +from excelCellBorder import * + re_RC=re.compile(r'R(?:\[(\d+)\])?C(?:\[(\d+)\])?') re_absRC=re.compile(r'^R(\d+)C(\d+)(?::R(\d+)C(\d+))?$') @@ -958,6 +960,11 @@ class ExcelCellTextInfo(NVDAObjectTextInfo): formatField['background-color']=colors.RGB.fromCOLORREF(int(cellObj.interior.color)) except COMError: pass + if formatConfig["reportBorderStyle"]: + try: + formatField['border-style']=getCellBorderStyleDescription(cellObj.borders) + except COMError: + pass return formatField,(self._startOffset,self._endOffset) class ExcelCell(ExcelBase): diff --git a/source/config/__init__.py b/source/config/__init__.py index d7cf7bd..f1fca37 100644 --- a/source/config/__init__.py +++ b/source/config/__init__.py @@ -181,6 +181,7 @@ confspec = ConfigObj(StringIO( reportRevisions = boolean(default=true) reportEmphasis = boolean(default=false) reportColor = boolean(default=False) + reportBorderStyle = boolean(default=True) reportAlignment = boolean(default=false) reportLineSpacing = boolean(default=false) reportStyle = boolean(default=false) diff --git a/source/speech.py b/source/speech.py index c213b05..654df8f 100755 --- a/source/speech.py +++ b/source/speech.py @@ -1160,6 +1160,15 @@ def getFormatFieldSpeech(attrs,attrsCache=None,formatConfig=None,unit=None,extra # A style is a collection of formatting settings and depends on the application. text=_("default style") textList.append(text) + if formatConfig["reportBorderStyle"]: + borderStyle=attrs.get("border-style") + oldBorderStyle=attrsCache.get("border-style") if attrsCache is not None else None + if borderStyle!=oldBorderStyle: + if borderStyle: + text=borderStyle + else: + text=_("no border lines") + textList.append(text) if formatConfig["reportFontName"]: fontFamily=attrs.get("font-family") oldFontFamily=attrsCache.get("font-family") if attrsCache is not None else None
罫線の色の処理を追加してみた。
まだ「上下左右」「上下」「左右」などの説明をまとめる処理を実装していない。
bright red continuous line at the bottom edge B6 bright red continuous line at the left edge, bright red continuous line at the top edge, bright red continuous line at the bottom edge, bright red continuous line at the right edge B7 bright red continuous line at the top edge, aqua-blue continuous line at the bottom edge B8 aqua-blue continuous line at the left edge, aqua-blue continuous line at the top edge B9 through C10 aqua-blue continuous line at the top edge, black double line at the bottom edge B11 black double line at the top edge B12 black double line at the bottom edge B13 black double line at the top edge, black continuous line at the bottom edge B14 black continuous line at the top edge, black continuous line at the bottom edge B15 black continuous line at the top edge B16 black dash followed by two dots at the left edge, black dash followed by two dots at the right edge B17 no border lines B18
#NVDAObjects/window/excelCellBorder.py import colors def getCellBorderStyleDescription(bordersObj): items=[] for pos in bordersIndexLabels.keys(): if bordersObj[pos].lineStyle != xlLineStyleNone: items.append(_("{color} {style} {position}").format( position=bordersIndexLabels.get(pos), style=borderStyleLabels.get(bordersObj[pos].lineStyle), color=colors.RGB.fromCOLORREF(int(bordersObj[pos].color)).name )) return ', '.join(items)
セル結合しているときに、結合する前の左上のセルの罫線しか取れていないことに気づいた:
aqua-blue continuous line at the left edge, aqua-blue continuous line at the top edge B9 through C10
実際には B9 から C10 まで4つのセルが結合されてひとつになっていて、その4つのセルが選択状態になり、 上下左右が aqua-blue continuous line である。
セル結合への対応がわかったので、英語で原文を組み立てて、nvda.po で日本語化する実装を試してみた:
日本語:
下はブラックの色の実線 B1 ブラックの色の実線の囲み線 B2 B3 上はブラックの色の実線 B4 右上がり線と右下がり線はブラックの色の実線 B5 下は明るい レッドの色の実線 B6 明るい レッドの色の実線の囲み線 B7 上は明るい レッドの色の実線, 下はアクアブルーの色の実線 B8 アクアブルーの色の実線の囲み線 B9 から C10 上はアクアブルーの色の実線, 下はブラックの色の2本線 B11 上はブラックの色の2本線 B12 下はブラックの色の2本線 B13 上はブラックの色の2本線, 下はブラックの色の実線 B14 上下はブラックの色の実線 B15 上はブラックの色の実線 B16 左右はブラックの色の二点鎖点 B17 罫線なし B18 左右はブラックの色の実線 B19 罫線なし B20
英語:
black continuous bottom edge B1 black continuous surrounding border B2 B3 black continuous top edge B4 black continuous up-right and down-right diagonal lines B5 bright red continuous bottom edge B6 bright red continuous surrounding border B7 bright red continuous top edge, aqua-blue continuous bottom edge B8 aqua-blue continuous surrounding border B9 through C10 aqua-blue continuous top edge, black double bottom edge B11 black double top edge B12 black double bottom edge B13 black double top edge, black continuous bottom edge B14 black continuous top and bottom edges B15 black continuous top edge B16 black dash followed by two dots left and right edges B17 no border lines B18 black continuous left and right edges B19 no border lines B20
線の種類の(英語での)説明が Excel のセル書式設定ダイアログと違うという話なので確認してみた
英語:
None radio button checked Hair radio button checked Dotted radio button checked DashDotDot radio button checked DashDot radio button checked Dashed radio button checked Thin radio button checked MediumDashDotDot radio button checked SlantedDashDot radio button checked MediumDashDot radio button checked MediumDashed radio button checked Medium radio button checked Thick radio button checked Double radio button checked
日本語
なし ラジオボタン チェック 細線 ラジオボタン チェック 点線 ラジオボタン チェック 二点鎖線 ラジオボタン チェック 一点鎖線 ラジオボタン チェック 破線 ラジオボタン チェック 実線 ラジオボタン チェック 実線 (二点鎖線) ラジオボタン チェック 傾斜 (一点鎖線) ラジオボタン チェック 実線 (一点鎖線) ラジオボタン チェック 実線 (破線) ラジオボタン チェック 太線 ラジオボタン チェック 極太線 ラジオボタン チェック 二重線 ラジオボタン チェック なし ラジオボタン チェック
下記を考慮しないと「セルの書式設定」で選べる罫線の種類すべてをカバーできない。
XlBorderWeight Enumeration
https://msdn.microsoft.com/en-us/library/office/ff197515.aspx
日本語
https://msdn.microsoft.com/ja-jp/library/office/ff197515.aspx
xlHairline 1 細線 (最も細い罫線) xlThin 2 極細 xlMedium -4138 普通 xlThick 4 太線 (最も太い罫線)
「極細」ではなく「細線」が最も細いという定義になっている。 あまり MSDN の訳語を真に受けない方がよいかも。
線の太さを付け加えたが、 このままだとセル書式設定ダイアログのラジオボタンと説明が違うので、 もうすこし作業が必要。。
black continuous thinnest surrounding border Hair B4 black dotted thin surrounding border Dotted B6 black dash followed by two dots thin surrounding border DashDotDot B8 black alternating dashes and dots thin surrounding border DashDot B10 black dashed thin surrounding border Dashed B12 black continuous thin surrounding border Thin B14 black dash followed by two dots medium surrounding border MediumDashDotDot D2 black slanted dashes medium surrounding border SlantedDashDot D4 black alternating dashes and dots medium surrounding border MediumDashDot D6 black dashed medium surrounding border MediumDashed D8 black continuous medium surrounding border Medium D10 black continuous thick surrounding border Thick D12 black double thick surrounding border Double D14
英語に関する作業は本家 3044
https://github.com/nvaccess/nvda/issues/3044
https://docs.com/nishimotz/8981/borders
Sheet2 を日本語で読ませた場合:
罫線なし None B2 ブラックの色の細線の囲み線 Hair B4 ブラックの色の点線の囲み線 Dotted B6 ブラックの色の二点鎖線の囲み線 DashDotDot B8 ブラックの色の一点鎖線の囲み線 DashDot B10 ブラックの色の破線の囲み線 Dashed B12 ブラックの色の実線の囲み線 Thin B14 ブラックの色の実線(二点鎖線)の囲み線 MediumDashDotDot D2 ブラックの色の傾斜(一点鎖線)の囲み線 SlantedDashDot D4 ブラックの色の実線(一点鎖線)の囲み線 MediumDashDot D6 ブラックの色の実線(破線)の囲み線 MediumDashed D8 ブラックの色の太線の囲み線 Medium D10 ブラックの色の極太線の囲み線 Thick D12 ブラックの色の二本線の囲み線 Double D14
そろそろ日本語ベータ版に入れてみようか。。
2016.4jp-beta-161014 として jpbeta ではなく i3044v2 ブランチのビルドを リリースしてみる予定。
メモ:下記のようなときに「左」「右」の順番のほうが自然に思える。
右はブラックの色の傾斜(一点鎖線), 左はブラックの色の細線 C4
色の報告がチェックなしの場合は罫線の色の報告もしないのが適切に思えてきた。
2016.4jp-beta-161018 にて「日本語設定」にセルの罫線の設定オプションを追加。 「なし」「スタイル」「色とスタイル」から選択可能にしました。
点字ディスプレイ出力には未対応です。
本家チケット 3044 へのプルリクエストの段階では、 本来あるべき「書式情報」の設定ダイアログに移動するつもりです。
メモ:reportColor パラメータが Font グループに仕分けされた経緯は下記
https://github.com/nvaccess/nvda/issues/6348
そうでなければ reportColor を「罫線の色の報告」に使おうと思った。。
本家にプルリクエストを作成:
「日本語版の説明」に本件の記述を追加しました。 NVDA日本語版としては作業終了としますが、説明のまとめ方や言葉の選び方、互換性の問題など、フィードバックを待ちたいと思います。
本家への提案はまだレビューされていないので、本家 2016.4 に入ることはなさそうです。
別作業の途中に気づいたのでうろ覚えだが、FirefoxのブラウズモードでNVDA+Fを使うと下記のエラーになる。
ERROR - scriptHandler.executeScript (15:12:52): error executing script: <bound method GlobalCommands.script_reportFormatting of <globalCommands.GlobalCommands object at 0x05064F90>> with gesture u'NVDA+f' Traceback (most recent call last): File "scriptHandler.pyo", line 187, in executeScript File "globalCommands.pyo", line 1373, in script_reportFormatting File "speech.pyo", line 1312, in getFormatFieldSpeech KeyError: 'reportBorderStyle'
NVDA+F で reportBorderStyle を True にしておく:
diff --git a/source/globalCommands.py b/source/globalCommands.py index 6a74479..4d63efd 100755 --- a/source/globalCommands.py +++ b/source/globalCommands.py @@ -1351,6 +1351,7 @@ class GlobalCommands(ScriptableObject): "reportPage":False,"reportLineNumber":False,"reportLineIndentation":True,"reportLineIndentationWithTones":False,"reportParagraphIndentation":True,"reportLineSpacing":True,"reportTables":False, "reportLinks":False,"reportHeadings":False,"reportLists":False, "reportBlockQuotes":False,"reportComments":False, + "reportBorderStyle":True, } textList=[] info=api.getReviewPosition()
Excel でセルに罫線があるかどうかを確認する方法が、セルごとに Ctrl+1 「セルの書式設定」タブ「罫線」で各方向の罫線のボタンに移動してチェックかどうかを調べるしかない、とのこと。
背景色など他の書式情報の報告はかなり充実しているので、要望を上げたり実装を提案すれば本家に受理されるものと思われる。