チケット #36621

Excel セルの罫線の報告

登録: 2016-09-04 21:28 最終更新: 2016-11-24 18:54

報告者:
担当者:
(未割り当て)
チケットの種類:
状況:
完了
コンポーネント:
マイルストーン:
優先度:
5 - 中
重要度:
5 - 中
解決法:
修正済み
ファイル:
なし

詳細

Excel でセルに罫線があるかどうかを確認する方法が、セルごとに Ctrl+1 「セルの書式設定」タブ「罫線」で各方向の罫線のボタンに移動してチェックかどうかを調べるしかない、とのこと。

背景色など他の書式情報の報告はかなり充実しているので、要望を上げたり実装を提案すれば本家に受理されるものと思われる。

チケットの履歴 (25 件中 3 件表示)

2016-09-04 21:28 更新者: nishimoto
  • 新しいチケット "Excel セルの罫線の報告" が作成されました
2016-09-09 15:37 更新者: nishimoto
コメント

本家チケット 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

メモ:

  • Excel セルの罫線 = Borders
  • Excel グラフの縦横の目盛線 = MajorGridlines 補助目盛線 = MinorGridlines
2016-10-09 22:05 更新者: nishimoto
コメント

手元の作業ファイルでは罫線を説明できる目処が立ったが、 まず英語でどのように文章化する仕様がよいのか、 それを適切に日本語化できるためにはどういうローカライズの実装がよいのか。。

以下は 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
2016-10-09 22:08 更新者: nishimoto
コメント

ここまでの作業(本家 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
2016-10-10 10:05 更新者: nishimoto
コメント

仮に「上下は黒の実線、左右は黒の細線」のように報告させるとすると、

  • 上下左右が同じ場合
  • 上下のみ同じ場合、左右のみ同じ場合
  • それ以外

のように優先順位をつけて、まとめて文章化する必要がある。

また、線の色を取得する API が未検証(たぶんできるが)。

英語のメッセージと、gettext のテンプレート、日本語のローカライズ、同時に考えた方がいいかも。。

2016-10-10 19:23 更新者: nishimoto
コメント

本家のコードをいじりたくないのでソースを分割した:

#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
2016-10-10 20:50 更新者: nishimoto
コメント

罫線の色の処理を追加してみた。

まだ「上下左右」「上下」「左右」などの説明をまとめる処理を実装していない。

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)
2016-10-12 12:20 更新者: nishimoto
コメント

セル結合しているときに、結合する前の左上のセルの罫線しか取れていないことに気づいた:

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 である。

2016-10-12 19:00 更新者: nishimoto
コメント

セル結合への対応がわかったので、英語で原文を組み立てて、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
2016-10-13 15:28 更新者: nishimoto
コメント

線の種類の(英語での)説明が 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

日本語

なし  ラジオボタン  チェック
細線  ラジオボタン  チェック
点線  ラジオボタン  チェック
二点鎖線  ラジオボタン  チェック
一点鎖線  ラジオボタン  チェック
破線  ラジオボタン  チェック
実線  ラジオボタン  チェック
実線 (二点鎖線)  ラジオボタン  チェック
傾斜 (一点鎖線)  ラジオボタン  チェック
実線 (一点鎖線)  ラジオボタン  チェック
実線 (破線)  ラジオボタン  チェック
太線  ラジオボタン  チェック
極太線  ラジオボタン  チェック
二重線  ラジオボタン  チェック
なし  ラジオボタン  チェック
2016-10-13 16:18 更新者: nishimoto
コメント

下記を考慮しないと「セルの書式設定」で選べる罫線の種類すべてをカバーできない。

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 の訳語を真に受けない方がよいかも。

2016-10-13 21:17 更新者: nishimoto
コメント

線の太さを付け加えたが、 このままだとセル書式設定ダイアログのラジオボタンと説明が違うので、 もうすこし作業が必要。。

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
2016-10-14 15:51 更新者: nishimoto
コメント

英語に関する作業は本家 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-10-14 16:05 更新者: nishimoto
  • 解決法なし から 受領 に更新されました
  • マイルストーン(未割り当て) から 2016.4jp (完了済み) に更新されました
2016-10-14 16:25 更新者: nishimoto
コメント

2016.4jp-beta-161014 として jpbeta ではなく i3044v2 ブランチのビルドを リリースしてみる予定。

メモ:下記のようなときに「左」「右」の順番のほうが自然に思える。

右はブラックの色の傾斜(一点鎖線), 左はブラックの色の細線
C4
2016-10-16 15:42 更新者: nishimoto
コメント

色の報告がチェックなしの場合は罫線の色の報告もしないのが適切に思えてきた。

2016-10-18 23:07 更新者: nishimoto
  • 解決法受領 から 修正済み に更新されました
コメント

2016.4jp-beta-161018 にて「日本語設定」にセルの罫線の設定オプションを追加。 「なし」「スタイル」「色とスタイル」から選択可能にしました。

点字ディスプレイ出力には未対応です。

本家チケット 3044 へのプルリクエストの段階では、 本来あるべき「書式情報」の設定ダイアログに移動するつもりです。

2016-10-18 23:24 更新者: nishimoto
コメント

メモ:reportColor パラメータが Font グループに仕分けされた経緯は下記

https://github.com/nvaccess/nvda/issues/6348

そうでなければ reportColor を「罫線の色の報告」に使おうと思った。。

2016-10-21 19:57 更新者: nishimoto
コメント

本家にプルリクエストを作成:

https://github.com/nvaccess/nvda/pull/6492

2016-10-31 22:34 更新者: nishimoto
コメント

「日本語版の説明」に本件の記述を追加しました。 NVDA日本語版としては作業終了としますが、説明のまとめ方や言葉の選び方、互換性の問題など、フィードバックを待ちたいと思います。

本家への提案はまだレビューされていないので、本家 2016.4 に入ることはなさそうです。

2016-11-18 23:06 更新者: nishimoto
コメント

別作業の途中に気づいたのでうろ覚えだが、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'
2016-11-21 11:35 更新者: nishimoto
コメント

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()
2016-11-24 18:54 更新者: nishimoto
  • 状況オープン から 完了 に更新されました
  • チケット完了時刻2016-11-24 18:54 に更新されました

添付ファイルリスト

添付ファイルはありません

編集

このチケットにコメントを追加するには、ログインが必要です » ログインする