はじめに
前回までの記事でCSVファイルの並び替えやウィンドウ枠の固定など、データ解析をするときに良く設定する手順を自動化できた。
実際にデータ解析をしていると、値がある条件の時にセルや文字の装飾などして解析しやすくすることが多く、ある程度は条件付き書式でいくつかルールを設けて解析しやすくしている。
前回までに作成したコードを拡張して、解析するデータに自動で条件付き書式を設定できるようにした。
今回やってみたこと
- 条件付き書式を自動設定できるようにした
今後のレベルアップ項目
- いまのところ思い浮かばない...
追加した機能
- 解析データに条件付き書式を設定して、セルの背景を変更できるようにした
実装
ファイル構成
+---csv2xlsx
result_code.py # 共通の戻り値定義
command_line.py # コマンドライン解析用
const_excel.py # Excel VBAの定数定義
simple_excel.py # 簡易Excel制御クラス
format_condition.py # 条件付き書式の設定クラス
main.py # メイン処理
サンプルコード
全コード
result_code.py : 共通の戻り値定義
ソースコード間で戻り値を共通化するために作成。
from enum import IntEnum
class ResultCode(IntEnum):
""" 戻り値 """
SUCCESS = 0
ERROR = -1
command_line.py : コマンドライン解析用
コマンドラインの解析処理をメイン処理と分離するため別ファイルで処理した。
いつも似たようなコード書いているので、作成するアプリごとに編集して使いまわせればと思っています。
import os
import argparse
from result_code import ResultCode
# カレントディレクトリ・ファイルパス
APP_PATH = os.getcwd()
FILE_PATH = os.path.dirname(__file__)
class CommandParam():
""" コマンドパラメータクラス """
path_csvfile: str
path_output: str
def check_commandline(param: CommandParam) -> ResultCode:
"""
コマンドラインチェック
Args:
param (class) : (out)コマンドパラメータ
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : 引数エラー
"""
result = ResultCode.SUCCESS
# コマンドライン パラメータ
parser = argparse.ArgumentParser(
description='Aout WinMerge Tool', add_help=True)
parser.add_argument('arg1', help='CSVファイルのパス')
parser.add_argument('arg2', help='出力先ファイル名&パス')
args = parser.parse_args()
# パスチェック
if not os.path.isfile(args.arg1):
print(f'{args.arg1} が見つかりません')
result = ResultCode.ERROR
# コマンドラインパラメータの保存
if result == ResultCode.SUCCESS:
param.path_csvfile = args.arg1
param.path_output = args.arg2
return result
const_excel.py:Excel VBAの定数定義
Excel制御で使用する定数を定義する。下記のサイトを参考に必要な定義のみ抜き出しました。(地味に面倒な作業なので、とても助かりました)
・Python pywin32(win32com) Excel 操作備忘録
# region XlFileFormat 定義:ファイル保存フォーマット
xlCSV = 6
xlHtml = 44
xlWorkbookDefault = 51
xlOpenXMLWorkbook = 51
xlOpenXMLWorkbookMacroEnabled = 52
xlWorkbookNormal = -4143
xlCurrentPlatformText = -4158
# endregion
# region XlYesNoGuess 定義:Yes/No
xlGuess = 0
xlYes = 1
xlNo = 2
# endregion
# region XlSortOrder 定義:ソート順
xlAscending = 1
xlDescending = 2
xlManual = -4135
# endregion
# region XlSortOrientation 定義:ソート方向(列・行)
xlSortColumns = 1
xlSortRows = 2
# endregion
# region XlSortMethod 定義:ソート条件:ふりがなの使用・不使用
xlPinYin = 1
xlStroke = 2
# endregion
# region XlDeleteShiftDirection 列挙型:削除後にセルをシフトするかを指定
# XlInsertShiftDirection 列挙型:挿入時にセルをシフトする方向を指
xlShiftUp = -4162 # セルは上にシフトします
xlShiftToLeft = -4159 # セルは左にシフトします
xlShiftDown = -4121 # セルを挿入後、下に伸ばす
xlShiftToRight = -4161 # セルを挿入後、右に伸ばす
# endregion
# region XlFormatConditionType 列挙型:条件付き書式を設定
xlAboveAverageCondition = 12 # 平均以上の条件
xlBlanksCondition = 10 # 空白の条件
xlCellValue = 1 # セルの値
xlColorScale = 3 # カラー スケール
xlDataBar = 4 # DataBar
xlErrorsCondition = 16 # エラー条件
xlExpression = 2 # Expression
xlIconSet = 6 # アイコン セット
xlNoBlanksCondition = 13 # 空白の条件なし
xlNoErrorsCondition = 17 # エラー条件なし
xlTextString = 9 # テキスト文字列
xlTimePeriod = 11 # 期間
xlTop10 = 5 # 上から 10 個の値
xlUniqueValues = 8 # 一意の値
# endregion
# region Constants 列挙型:Microsoft Excel で使用されるグローバル定数
xlAbove = 0
xlBelow = 1
xlSolid = 1
xlFirst = 0
xlLast = 1
xlLastCell = 11
xlTopToBottom = 1
xlLeftToRight = 2
xlGeneral = 1
xlAutomatic = -4105
xlFormats = -4122
xlNone = -4142
xlCenter = -4108
xlDistributed = -4117
xlJustify = -4130
xlBottom = -4107
xlLeft = -4131
xlRight = -4152
xlTop = -4160
xlRTL = -5004
xlLTR = -5003
xlContext = -5002
# endregion
# region XlThemeColor
xlThemeColorAccent1 = 5 # Accent1
xlThemeColorAccent2 = 6 # Accent2
xlThemeColorAccent3 = 7 # Accent3
xlThemeColorAccent4 = 8 # Accent4
xlThemeColorAccent5 = 9 # Accent5
xlThemeColorAccent6 = 10 # Accent6
xlThemeColorDark1 = 1 # Dark1
xlThemeColorDark2 = 3 # Dark2
xlThemeColorFollowedHyperlink = 12 # 表示済みのハイパーリンク
xlThemeColorHyperlink = 11 # ハイパーリンク
xlThemeColorLight1 = 2 # Light1
xlThemeColorLight2 = 4 # Light2
# endregion
def rgb(col_r: int,
col_g: int,
col_b: int) -> int:
return (col_b * 256 * 256 + col_g * 256 + col_r)
xlColBlack = rgb(0, 0, 0)
xlColWhite = rgb(255, 255, 255)
xlColRed = rgb(255, 0, 0)
xlColGreen = rgb(0, 255, 0)
xlColBlue = rgb(0, 0, 255)
xlColGainsboro = rgb(220, 220, 220)
xlColLightGray = rgb(211, 211, 211)
xlColSilver = rgb(192, 192, 192)
xlColDarkGray = rgb(169, 169, 169)
xlColGray = rgb(128, 128, 128)
色の定義がちょっと少ない。
下記のページを参考によく使う色を増やしていければよいと思います。
・Webで使えるカラーネームと、そのカラーコード・RGB値一覧
simple_excel.py:簡易Excel制御クラス
Excel制御する処理をクラス化。
今回は、条件付き書式を設定するメソッドを追加した。
import os
import win32com.client
import const_excel as xl
from result_code import ResultCode
from format_condition import Font, Interior
# カレントディレクトリ・ファイルパス
APP_PATH = os.getcwd()
FILE_PATH = os.path.dirname(__file__)
# 定数定義
# region デフォルト定義
DEFAULT_VISIBLE = True # Excel表示
DEFAULT_FORCED_WRITE = False # 上書き保存の強制有無
# endregion
class SimpleExcel:
"""
Excel制御クラス
"""
# 定数定義
# region パラメータ定数
AUTO_FIT = -1 # 行・高さの自動調整
MAX_USED_COLUMNS = -1 # 使用している列の最大値
MAX_USED_ROWS = -1 # 使用している行の最大値
NOTHING = 0 # 指定しない
# endregion
# region コンストラクタ
def __init__(self,
visibled: bool = DEFAULT_VISIBLE):
"""
コンストラクタ
"""
self.__xlapp = None
self.__visibled = visibled
# endregion
# region デストラクタ
def __del__(self):
"""
デストラクタ
"""
try:
# ワークブックを閉じる
if self.__wbook is not None:
self.__wbook.Close(SaveChanges=False)
# Excelを閉じる
if self.__xlapp is not None:
self.__xlapp.Quit()
except Exception as e:
# すでにExcel終了済みならエラー無視する
if type(e).__name__ != 'com_error':
print(f"終了処理に失敗しました\n{e}")
# endregion
# region プロパティ
# region Excel表示On/Off
@property
def visibled(self) -> bool:
"""
Excel表示On/Off
"""
return self.__visibled
@visibled.setter
def visibled(self,
value: bool):
"""
Excel表示On/Off
Args:
value : (in) True = 表示On
"""
self.__visibled = value
if self.__xlapp is not None:
self.__xlapp.Visible = value
# endregion
# region アクティブシートで使用されている列数
@property
def get_count_columns(self) -> int:
"""
アクティブシートで使用されている列数
"""
result = self.__wsheet.UsedRange.Columns(
self.__wsheet.UsedRange.Columns.Count).Column
return result
# endregion
# region アクティブシートで使用されている行数
@property
def get_count_rows(self) -> int:
"""
アクティブシートで使用されている行数
"""
result = self.__wsheet.UsedRange.Rows(
self.__wsheet.UsedRange.Rows.Count).Row
return result
# endregion
# endregion
# region 公開メソッド
# region Excelでファイルを開く
def open(self,
file_path: str) -> ResultCode:
"""
Excelでファイルを開く
Args:
file_path : (in) 読込むファイル名&パス
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : オープンエラー
"""
result = ResultCode.SUCCESS
if not os.path.isfile(file_path):
print(f"{file_path} が見つかりません")
result = ResultCode.ERROR
else:
try:
# Excelを起動してファイルを開く
if self.__xlapp is None:
self.__xlapp = win32com.client.Dispatch(
'Excel.Application')
self.__xlapp.Visible = self.__visibled
self.__wbook = self.__xlapp.Workbooks.Open(file_path)
self.select_sheet(1)
except Exception as e:
print(f"ファイルオープンに失敗しました\n{e}")
result = ResultCode.ERROR
return result
# endregion
# region ワークブックを閉じる
def close(self):
"""
ワークブックを閉じる
Args:
なし
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : クローズエラー(未定義)
"""
result = ResultCode.SUCCESS
if self.__wbook is not None:
self.__wbook.Close(SaveChanges=False)
return result
# endregion
# region 名前を付けて保存
def save_as(self,
file_path: str,
format: xl = xl.xlOpenXMLWorkbook,
forced_write: bool = DEFAULT_FORCED_WRITE) -> ResultCode:
"""
名前を付けて保存
Args:
file_path : (in) 保存するファイル名&パス
format : (in) 保存形式
forced_write : (in) True=強制的に上書きする
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : 保存エラー
"""
result = ResultCode.SUCCESS
# Excelファイル(xlsx)形式で保存する
if self.__wsheet is not None:
try:
if forced_write:
# 警告メッセージを非表示にする(強制的に上書きする)
self.__xlapp.DisplayAlerts = False
# 名前を付けて保存する
self.__wsheet.SaveAs(file_path, FileFormat=format)
if forced_write:
# 警告メッセージ表示を元に戻す
self.__xlapp.DisplayAlerts = True
except Exception as e:
print(f"ファイルの書き込みに失敗しました\n{e}")
result = ResultCode.ERROR
return result
# endregion
# region セル選択(移動)
def select_cell(self,
row: int,
column: int) -> ResultCode:
"""
セル選択(移動)
Args:
row : (in) 行番号
column : (in) 列番号
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : エラー(未定義)
"""
result = ResultCode.SUCCESS
range_cell = self.conv_r1c1_to_a1(row, column)
self.__wsheet.Range(range_cell).Select()
return result
# endregion
# region シートを選択する
def select_sheet(self,
name: any) -> any:
"""
シートを選択する
Args:
name : (in) シート名 or シート番号
returns:
シートオブジェクト
"""
# シート名またはシート番号での指定
self.__wsheet = self.__wbook.Worksheets(name)
return self.__wsheet
# endregion
# region 列の並び替えをする
def sort_column(self,
key1_row: int,
order1: int = xl.xlAscending) -> ResultCode:
"""
列の並び替えをする
Args:
key1_row : (in) 並べ替えのキーになる行番号(1~)
order1 : (in) 並べ替え順序
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : 並べ替えエラー(未定義)
"""
result = ResultCode.SUCCESS
# 並び替えキーのカラム文字作成(行指定)
col_str = self.conv_r1c1_to_a1(key1_row, 1)
range_key = self.__wsheet.Range(col_str)
# 並び替え範囲のカラム文字作成(シートの使用領域全体)
range_sort = self.covn_range_r1c1_to_a1(
1, 1, self.get_count_rows, self.get_count_columns)
# シートの並び替え
self.__wsheet.Sort.SortFields.Clear
self.__wsheet.Sort.SortFields.Add(Key=range_key, Order=order1)
self.__wsheet.Sort.SetRange(self.__wsheet.Range(range_sort))
self.__wsheet.Sort.Header = xl.xlYes
self.__wsheet.Sort.Orientation = xl.xlSortRows
self.__wsheet.Sort.MatchCase = False
self.__wsheet.Sort.SortMethod = xl.xlPinYin
self.__wsheet.Sort.Apply()
return result
# endregion
# region カラム文字変換
# region 列番号 → A1形式のカラム文字に変換
def conv_colindex_to_addr(self,
column: int) -> str:
"""
列番号 → A1形式のカラム文字に変換
Args:
column : (in) 列番号
returns:
A1形式のカラム文字
"""
return (self.__wsheet.Cells(1, column).Address).split("$")[1]
# endregion
# region R1C1指定 → A1形式に変換
def conv_r1c1_to_a1(self,
row: int,
column: int) -> str:
"""
R1C1指定 → A1形式に変換
Args:
row : (in) 行番号
column : (in) 列番号
returns:
A1形式
"""
if row == self.NOTHING:
# 列指定
result = f'{self.conv_colindex_to_addr(column)}'
elif column == self.NOTHING:
# 行指定
result = f'{row}'
else:
# 行&列指定
result = f'{self.conv_colindex_to_addr(column)}{row}'
return result
# endregion
# region R1C1指定 → A1形式の範囲文字に変換
def covn_range_r1c1_to_a1(self,
row1: int,
column1: int,
row2: int,
column2: int) -> str:
"""
R1C1指定 → A1形式の範囲文字に変換
Args:
row1 : (in) 行番号(左上)
column1 : (in) 列番号(左上)
row2 : (in) 行番号(右下)
column2 : (in) 列番号(右下)
returns:
A1形式の範囲文字
"""
# パラメータ指定の場合、変換する
row1 = self.__conv_param_rows(row1)
row2 = self.__conv_param_rows(row2)
column1 = self.__conv_param_columns(column1)
column2 = self.__conv_param_columns(column2)
return \
f'{self.conv_r1c1_to_a1(row1, column1)}:' \
f'{self.conv_r1c1_to_a1(row2, column2)}'
# endregion
# endregion
# region シートをコピーする
def sheet_copy(self,
sheet_base: any,
sheet_after: any) -> ResultCode:
"""
シートをコピーする
Args:
sheet_base : (in) コピー元のシート
sheet_after : (in) コピー先のシート名(またはシート番号)
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : コピーエラー(未定義)
"""
result = ResultCode.SUCCESS
# シートのコピー
# ※Beforeを省略すると、Afterも無効になるのか新規ブックが作成される
sheet_base.Copy(
Before=None, After=self.__wbook.Worksheets(sheet_after))
return result
# endregion
# region ウィンドウ枠を固定する
def freeze_window(self,
row: int,
column: int) -> ResultCode:
"""
ウィンドウ枠を固定する
Args:
row : (in) 固定する行番号(NOTHING=指定しない)
column : (in) 固定する列番号(NOTHING=指定しない)
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : コピーエラー(未定義)
"""
result = ResultCode.SUCCESS
# ウィンドウ枠を固定する
self.__wsheet.Activate()
range_freeze = self.__wsheet.Range(
self.covn_range_r1c1_to_a1(row, column, row, column))
range_freeze.Select()
self.__wsheet.Parent.Windows(1).FreezePanes = True
return result
# endregion
# region オートフィルタをセットする
def set_auto_filter(self,
row: int) -> ResultCode:
"""
オートフィルタをセットする
Args:
row : (in) 定義する行番号
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : エラー(未定義)
"""
result = ResultCode.SUCCESS
self.__wsheet.Activate()
range_filter = self.__wsheet.Range(
self.covn_range_r1c1_to_a1(
row, 1, self.get_count_rows, self.get_count_columns))
range_filter.AutoFilter()
return result
# endregion
# region 列の幅を変更する
def change_column_size(self,
size: float,
column1: int,
column2: int):
"""
列の幅を変更する
Args:
size : (in) 列の幅
column1 : (in) 列番号(開始)
column2 : (in) 列番号(終了)
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : エラー(未定義)
"""
result = ResultCode.SUCCESS
self.__wsheet.Activate()
range_width = self.__wsheet.Range(
self.covn_range_r1c1_to_a1(
self.NOTHING, column1, self.NOTHING, column2))
if size == self.AUTO_FIT:
range_width.EntireColumn.AutoFit()
else:
range_width.ColumnWidth = size
return result
# endregion
# region 行の高さを変更する
def change_row_size(self,
size: float,
row1: int,
row2: int):
"""
行の高さを変更する
Args:
size : (in) 行の高さ
row1 : (in) 行番号(開始)
row2 : (in) 行番号(終了)
returns:
ResultCode.SUCCESS : 正常
ResultCode.ERROR : エラー(未定義)
"""
result = ResultCode.SUCCESS
self.__wsheet.Activate()
range_height = self.__wsheet.Range(
self.covn_range_r1c1_to_a1(row1, self.NOTHING, row2, self.NOTHING))
if size == self.AUTO_FIT:
range_height.EntireRow.AutoFit()
else:
range_height.RowHeight = size
return result
# endregion
# region 条件付き書式設定
def set_format_condition(self,
range: str,
formula: str,
setting_font: Font,
setting_interior: Interior):
"""
条件付き書式設定
"""
result = ResultCode.SUCCESS
self.__wsheet.Activate()
settings = range.FormatConditions.Add(
Type=xl.xlExpression, Operator=None, Formula1=formula)
settings.Font.Bold = setting_font.bold
settings.Font.Italic = setting_font.italic
settings.Font.Color = setting_font.color
settings.Interior.Color = setting_interior.color
return result
# endregion
# endregion
# region 非公開メソッド
# region 行番号のパラメータ変換
def __conv_param_rows(self,
value) -> int:
"""
行番号のパラメータ変換
Args:
value : (in) 行番号orパラメータ指定
returns:
行番号
"""
result = value
if value == self.MAX_USED_ROWS:
result = self.get_count_rows
return result
# endregion
# region 列番号のパラメータ変換
def __conv_param_columns(self,
value) -> int:
"""
列番号のパラメータ変換
Args:
value : (in) 列番号orパラメータ指定
returns:
列番号
"""
result = value
if value == self.MAX_USED_COLUMNS:
result = self.get_count_columns
return result
# endregion
# endregion
format_condition.py:条件付き書式の設定クラス
条件付き書式の設定により、変更するセルの背景やフォント情報を設定するためのクラスを集めたファイル。今のところ、フォントとセルの背景くらいで困らないので、必要に応じて拡張していけば良いと思っています。
import const_excel as xl
# 定数定義
# region デフォルト定義
DEFAULT_FONT_COLOR = xl.xlColBlack # フォントカラー
DEFAULT_FONT_SIZE = 11 # フォントサイズ
DEFAULT_FONT_BOLD = False # フォント太字
DEFAULT_FONT_ITALIC = False # フォント太斜体
DEFAULT_INTERIOR_COLOR = xl.xlColWhite # セル背景色
# endregion
class Font:
"""
条件付き書式 - フォント設定クラス
"""
def __init__(self):
self.__color = DEFAULT_FONT_COLOR
self.__size = DEFAULT_FONT_SIZE
self.__bold = DEFAULT_FONT_BOLD
self.__italic = DEFAULT_FONT_ITALIC
# region プロパティ
# region フォントカラー
@property
def color(self):
"""
フォントカラー
"""
return self.__color
@color.setter
def color(self, value: int):
"""
フォントカラー
Args:
value : (in) フォントカラー(RGB値)
"""
self.__color = value
# endregion
# region フォントサイズ
@property
def size(self):
"""
フォントサイズ
"""
return self.__size
@size.setter
def size(self, value: bool):
"""
フォントサイズ
Args:
value : (in) フォントサイズ(ポイント)
"""
self.__size = value
# endregion
# region フォント太字
@property
def bold(self):
"""
フォント太字
"""
return self.__bold
@bold.setter
def bold(self, value: bool):
"""
フォント太字
Args:
value : (in) True=フォント太字
"""
self.__bold = value
# endregion
# region フォント斜体
@property
def italic(self):
"""
フォント斜体
"""
return self.__bold
@italic.setter
def italic(self, value: bool):
"""
フォント斜体
Args:
value : (in) True=フォント斜体
"""
self.__italic = value
# endregion
# endregion
class Interior:
"""
条件付き書式 - セル背景設定クラス
"""
def __init__(self):
self.__color = xl.rgb(255, 255, 255)
# region プロパティ
# region 背景カラー
@property
def color(self):
"""
背景カラー
"""
return self.__color
@color.setter
def color(self, value: int):
"""
背景カラー
Args:
value : (in) 背景カラー(RGB値)
"""
self.__color = value
# endregion
# endregion
main.py:メイン処理
import os
import command_line
from result_code import ResultCode
from command_line import CommandParam
from simple_excel import SimpleExcel, xl
from format_condition import Font, Interior
# カレントディレクトリ・ファイルパス
APP_PATH = os.getcwd()
FILE_PATH = os.path.dirname(__file__)
# 定数定義
EXCEL_BASE_FILE = 'test_base.xlsx'
EXCEL_BASE_SHEET_NAME = 'データ名一覧'
EXCEL_CELL_MACRO_NUMBER = f'=IF(ISERROR(VLOOKUP(A$3, ' \
f'{EXCEL_BASE_SHEET_NAME}!$A:$C, 3, FALSE)), "", ' \
f'VLOOKUP(A$3, {EXCEL_BASE_SHEET_NAME}!$A:$C, 3, FALSE))'
EXCEL_CELL_MACRO_NAME = f'=IF(ISERROR(VLOOKUP(A$3, ' \
f'{EXCEL_BASE_SHEET_NAME}!$A:$C, 2, FALSE)), "", ' \
f'VLOOKUP(A$3, {EXCEL_BASE_SHEET_NAME}!$A:$C, 2, FALSE))'
EXCEL_COLUMN_SIZE = 12.0
def main():
"""
CSVファイルを読込み、1行目をキーに並べ替えをして
Excel形式(xlsx)でファイル保存するサンプル
"""
# コマンドラインチェック
param = CommandParam()
ret = command_line.check_commandline(param)
# CSVファイルを開く
excel_csv = None
if ret == ResultCode.SUCCESS:
# インスタンス生成してファイルを開く
excel_csv = SimpleExcel()
ret = excel_csv.open(param.path_csvfile)
# ベースのExcelファイルを開く
excel_base = None
if ret == ResultCode.SUCCESS:
# インスタンス生成してファイルを開く
path_base = os.path.join(APP_PATH, EXCEL_BASE_FILE)
excel_base = SimpleExcel()
ret = excel_base.open(path_base)
# ベースファイルのシートをコピーする
if ret == ResultCode.SUCCESS:
wsheet_base = excel_base.select_sheet(EXCEL_BASE_SHEET_NAME)
excel_csv.sheet_copy(wsheet_base, 1)
# ベースファイルを閉じる
excel_base.close()
if ret == ResultCode.SUCCESS:
# 先頭から2行分の空行を挿入する
sheet_csv = excel_csv.select_sheet(1)
sheet_csv.Rows(1).Insert(Shift=xl.xlShiftDown)
sheet_csv.Rows(1).Insert(Shift=xl.xlShiftDown)
# ソート順とデータ名のセルマクロを書き込む
sheet_csv.Range("A1").Value = EXCEL_CELL_MACRO_NUMBER
sheet_csv.Range("A2").Value = EXCEL_CELL_MACRO_NAME
# 上記のマクロを横方向へコピーする
range_dest = sheet_csv.Range(
excel_csv.covn_range_r1c1_to_a1(
1, 2, 2, excel_csv.MAX_USED_COLUMNS))
sheet_csv.Range("A1:A2").Copy(Destination=range_dest)
# セルの文字を縮小して全体表示を設定する
range_data_name = sheet_csv.Range(
excel_csv.covn_range_r1c1_to_a1(
2, 1, 2, excel_csv.MAX_USED_COLUMNS))
range_data_name.ShrinkToFit = True
# 1行目をキーに列の並び替えをする
if ret == ResultCode.SUCCESS:
ret = excel_csv.sort_column(1, xl.xlDescending)
# 列の幅を変更する
if ret == ResultCode.SUCCESS:
ret = excel_csv.change_column_size(
EXCEL_COLUMN_SIZE, 1, excel_csv.MAX_USED_COLUMNS)
# 4行目でウィンドウ枠を固定する
if ret == ResultCode.SUCCESS:
ret = excel_csv.freeze_window(4, excel_csv.NOTHING)
# 3行目にオートフィルタを追加する
if ret == ResultCode.SUCCESS:
ret = excel_csv.set_auto_filter(3)
excel_csv.select_cell(1, 1)
if ret == ResultCode.SUCCESS:
# 条件付き書式設定のフォント、背景色を設定
setting_font = Font()
setting_font.color = xl.xlColBlack
setting_interior = Interior()
setting_interior.color = xl.xlColLightGray
# 条件付き書式設定
range_f = sheet_csv.Range("A1:F13")
excel_csv.set_format_condition(
range_f, '=$B1=1', setting_font, setting_interior)
# Excelファイル(xlsx)形式で保存する
if ret == ResultCode.SUCCESS:
ret = excel_csv.save_as(param.path_output, forced_write=False)
if ret == ResultCode.SUCCESS:
print(f'{param.path_output} に保存しました')
# 終了処理
if excel_base is not None:
del excel_base
if excel_csv is not None:
del excel_csv
if __name__ == "__main__":
main()
サンプルコードの詳細
条件付き書式設定
from format_condition import Font, Interior
...
# 条件付き書式設定のフォント、背景色を設定
setting_font = Font() # (※1)
setting_font.color = xl.xlColBlack
setting_interior = Interior() # (※2)
setting_interior.color = xl.xlColLightGray
# 条件付き書式設定
range_f = sheet_csv.Range("A1:F13") # (※3)
excel_csv.set_format_condition(
range_f, '=$B1=1', setting_font, setting_interior) # (※4)
...
(※1) 条件成立時に変更するフォント情報を設定する
(※2) 条件成立時に変更するセル情報を設定する。現状は背景色のみ
(※3) 条件付き書式設定を定義するセルの範囲を生成する
(※4) ※1~3の設定と合わせて、条件式を引数に渡すことで条件付き書式がシートに書き出される
実処理部
...
# region 条件付き書式設定
def set_format_condition(self,
range: str,
formula: str,
setting_font: Font,
setting_interior: Interior):
"""
条件付き書式設定
"""
result = ResultCode.SUCCESS
self.__wsheet.Activate()
# ※第2引数の「Operator=None」は省略できない...
settings = range.FormatConditions.Add(
Type=xl.xlExpression, Operator=None, Formula1=formula)
settings.Font.Bold = setting_font.bold
settings.Font.Italic = setting_font.italic
settings.Font.Color = setting_font.color
settings.Interior.Color = setting_interior.color
return result
# endregion
...
FormatConditions.Add()メソッドで条件付き書式を登録しているが、例のごとく、「数式を指定する」(Type=xl.xlExpression)場合に省略可能な Operatorを定義しないと例外が発生していた。VBAのメソッドを使用する場合、引数の途中は省略できない仕様なのかもしれないと理解しました。