🎃
memo
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 5 モーダル</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- モーダルを開くボタン -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
モーダルを開く
</button>
<!-- モーダルのHTML -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">モーダルタイトル</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
ここに内容を書きます。
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">閉じる</button>
<button type="button" class="btn btn-primary">保存する</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
function hasModeAbc(url) {
try {
const parsedUrl = new URL(url);
// searchParamsからmodeの値を取得して判定
return parsedUrl.searchParams.get('mode') === 'abc';
} catch (error) {
// URLのパースに失敗した場合はfalseを返す
return false;
}
}
// 使用例
console.log(hasModeAbc("https://example.com/?mode=abc")); // true
console.log(hasModeAbc("https://example.com/?foo=bar&mode=abc")); // true
console.log(hasModeAbc("https://example.com/?mode=abc&foo=bar")); // true
console.log(hasModeAbc("https://example.com/?mode=xyz&foo=bar")); // false
console.log(hasModeAbc("https://example.com/?foo=bar&mode=abc&baz=qux")); // true
その2
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation
def copy_data_validation(ws, fromCell, toCell):
"""
指定したセルのデータバリデーション(入力規則)をコピーする関数
:param ws: 対象のワークシート
:param fromCell: コピー元のセル(例: "A1")
:param toCell: コピー先のセル(例: "B1")
"""
# コピー元セルのデータバリデーションを取得
for dv in ws.data_validations.dataValidation:
if fromCell in dv.cells:
original_dv = dv
break
else:
raise ValueError(f"{fromCell} にデータバリデーションが見つかりません")
# プルダウンリスト(リスト制約)の場合
if original_dv.type == "list":
new_dv = DataValidation(
type="list",
formula1=original_dv.formula1, # リストの定義をコピー
allowBlank=original_dv.allowBlank,
showDropDown=original_dv.showDropDown,
showErrorMessage=original_dv.showErrorMessage,
showInputMessage=original_dv.showInputMessage,
prompt=original_dv.prompt,
promptTitle=original_dv.promptTitle,
error=original_dv.error,
errorTitle=original_dv.errorTitle,
errorStyle=original_dv.errorStyle
)
# コピー先セルに適用
new_dv.add(toCell)
# ワークシートにデータバリデーションを追加
ws.add_data_validation(new_dv)
else:
raise ValueError(f"{fromCell} のデータバリデーションはリスト型(プルダウン)ではありません")
# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active
# A1 から B1 に入力規則(プルダウン)をコピー
copy_data_validation(ws, "A1", "B1")
# 保存
wb.save("sample_copy.xlsx")
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation
# グローバル変数としてデータバリデーションを保持
original_dv = None
def copy_data_validation(ws, fromCell, toCell):
"""
指定したセルのデータバリデーション(入力規則)をコピーする関数
1回目は `original_dv` を取得して保持し、2回目以降は再利用する。
:param ws: 対象のワークシート
:param fromCell: コピー元のセル(例: "A1")
:param toCell: コピー先のセル(例: "B1")
"""
global original_dv # グローバル変数を使用
# 1回目の実行時はコピー元のデータバリデーションを取得
if original_dv is None:
for dv in ws.data_validations.dataValidation:
if fromCell in dv.cells:
original_dv = dv
break
else:
raise ValueError(f"{fromCell} にデータバリデーションが見つかりません")
# 直接コピー先セルに追加
original_dv.add(toCell)
# 再度ワークシートにデータバリデーションを適用(必須)
ws.add_data_validation(original_dv)
# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active
# 1回目のコピー(グローバル変数に保持)
copy_data_validation(ws, "A1", "B1")
# 2回目以降のコピー(`original_dv` を再利用)
copy_data_validation(ws, "A1", "C1")
copy_data_validation(ws, "A1", "D1")
# 保存
wb.save("sample_copy.xlsx")
from openpyxl import load_workbook
from openpyxl.worksheet.datavalidation import DataValidation
# グローバル変数としてデータバリデーションを保持
original_dv = None
def copy_data_validation(ws, fromCell, toCell):
"""
指定したセルのデータバリデーション(入力規則)をコピーする関数
`fromCell` と `toCell` は `ws.cell(row=y, column=x)` で取得されたセルオブジェクト
:param ws: 対象のワークシート
:param fromCell: コピー元のセルオブジェクト(例: ws.cell(row=1, column=1))
:param toCell: コピー先のセルオブジェクト(例: ws.cell(row=1, column=2))
"""
global original_dv # グローバル変数を使用
# 1回目の実行時はコピー元のデータバリデーションを取得
if original_dv is None:
cell_ref = fromCell.coordinate # A1 形式のセル参照
for dv in ws.data_validations.dataValidation:
if cell_ref in dv.cells:
original_dv = dv
break
else:
raise ValueError(f"{cell_ref} にデータバリデーションが見つかりません")
# 直接コピー先セルに追加
original_dv.add(toCell.coordinate)
# 再度ワークシートにデータバリデーションを適用(必須)
ws.add_data_validation(original_dv)
# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active
# A1 から B1 に入力規則をコピー
copy_data_validation(ws, ws.cell(row=1, column=1), ws.cell(row=1, column=2))
# C1, D1 へもコピー
copy_data_validation(ws, ws.cell(row=1, column=1), ws.cell(row=1, column=3))
copy_data_validation(ws, ws.cell(row=1, column=1), ws.cell(row=1, column=4))
# 保存
wb.save("sample_copy.xlsx")
ExcelFitToPageSetter
from openpyxl import load_workbook
def set_fit_to_page(ws):
"""
Excelの「次のページ数に合わせて印刷」を有効にし、
縦のページ数の制限を解除する(空白にする)。
:param ws: ワークシートオブジェクト
"""
# 次のページ数に合わせて印刷を有効化
ws.page_setup.fitToPage = True
# 横を1ページに収める
ws.page_setup.fitToWidth = 1
# 縦のページ数を「空白」にする(無制限)
ws.page_setup.fitToHeight = None
# 使用例
wb = load_workbook("sample.xlsx")
ws = wb.active
# 設定を適用
set_fit_to_page(ws)
# 保存
wb.save("sample_modified.xlsx")
from openpyxl import load_workbook
# ワークブックを読み込む
wb = load_workbook("sample.xlsx")
# ワークシートを取得する
ws = wb["Sheet1"]
# ページ設定を行う
ws.page_setup.fitToWidth = 1 # 横方向に1ページに収める
ws.page_setup.fitToHeight = 0 # 縦方向のページ数を無制限にする
# ワークブックを保存する
wb.save("sample_modified.xlsx")
from openpyxl import load_workbook
def copy_sheet(file_path, source_sheet_name, target_sheet_name):
# Excelブックを読み込み
wb = load_workbook(file_path)
# コピー元のシートを取得
if source_sheet_name not in wb.sheetnames:
raise ValueError(f"シート '{source_sheet_name}' が存在しません。")
source_sheet = wb[source_sheet_name]
# シートをコピー
copied_sheet = wb.copy_worksheet(source_sheet)
# コピーしたシートの名称を設定
copied_sheet.title = target_sheet_name
# ファイルを上書き保存
wb.save(file_path)
wb.close()
# 使用例
copy_sheet("sample.xlsx", "Sheet1", "Sheet1_Copy")
from openpyxl import load_workbook
from openpyxl.worksheet.worksheet import Worksheet
def copy_sheet_with_settings(file_path, source_sheet_name, target_sheet_name):
# Excelブックを読み込み
wb = load_workbook(file_path)
# コピー元のシートを取得
if source_sheet_name not in wb.sheetnames:
raise ValueError(f"シート '{source_sheet_name}' が存在しません。")
source_sheet = wb[source_sheet_name]
# シートをコピー
copied_sheet = wb.copy_worksheet(source_sheet)
copied_sheet.title = target_sheet_name
# 印刷範囲のコピー
if source_sheet.print_area:
copied_sheet.print_area = source_sheet.print_area
# 印刷オプションのコピー(ヘッダー、フッター、グリッド線、拡大縮小など)
copied_sheet.print_options.horizontalCentered = source_sheet.print_options.horizontalCentered
copied_sheet.print_options.verticalCentered = source_sheet.print_options.verticalCentered
copied_sheet.print_options.gridLines = source_sheet.print_options.gridLines
copied_sheet.print_options.headings = source_sheet.print_options.headings
# シートビュー(標準ビューや改ページプレビューの状態)をコピー
if hasattr(source_sheet, 'views') and source_sheet.views:
copied_sheet.views = source_sheet.views
# ファイルを上書き保存
wb.save(file_path)
wb.close()
# 使用例
copy_sheet_with_settings("sample.xlsx", "Sheet1", "Sheet1_Copy")
from openpyxl import load_workbook
def select_all_sheets_and_set_first_active(file_path):
# Excelブックを開く
wb = load_workbook(file_path)
# 全シートの選択を解除
for ws in wb.worksheets:
ws.sheet_view.tabSelected = False
# すべてのシートを選択状態にする
for ws in wb.worksheets:
ws.sheet_view.tabSelected = True
# 一番左のシートをアクティブにする
wb.active = 0 # 最初のシートをアクティブに設定
# ファイルを保存
wb.save(file_path)
wb.close()
# 使用例
select_all_sheets_and_set_first_active("sample.xlsx")
Excelの仕様
Excelでは「選択済みのシート は tabSelected=True のシートが 1つ以上ある状態」
ただし、「アクティブなシートは必ず1つだけ」 でなければならない
もし、すでに tabSelected=True のシートがあって、別のシートを tabSelected=True にすると どのシートがアクティブなのか不明確になる
openpyxlの内部動作
openpyxl は「アクティブなシートが必ず1つである」ことを期待している
tabSelected=True を複数のシートに設定するとき、一度 すべて False にしないと、どのシートがアクティブかの整合性が取れなくなる可能性がある
Excel のUIでは、 手動で「すべてのシートを選択」すると、自動的に1つのシートがアクティブになる 仕様になっているため、これを openpyxl でも再現するには、 一度すべて False にしてから True にする方が安全
/*
画面リロードから再表示完了までスピナーを表示するようにしたため
途中でjavascriptエラーが発生時に、スピナーが表示されっぱなしになることを防ぎたい。
( 処理に時間がかかっているのか、エラーがあるのか判断できなくなるから )
そのため、catchしてないjavascriptの例外を捕獲して
スピナーを消す。
その際、エラーの通知、および、詳細なデバッグ情報をconsole.error()をしておく
*/
window.addEventListener('error', function (event) {
let errorMessage = getErrorMessageOnGlobalError(event);
let isAlert = true;
/*
videoタグをカルーセルに入れてから、
カルーセルでページ切り替え中に、時々、
message : ResizeObserver loop completed with undelivered notifications.
のようなエラーメッセージで、ここに飛んでくる。原因不明である。
ただ、ここにエラーが飛んでくるだけで画面表示がおかしくなったりもしない
特に実害がないため、
ブラウザのデバッガーで見れるコンソールには出力しておくが、alert表示をしないことにした。
*/
let specialError00100 = errorMessage.includes('ResizeObserver loop completed');
if(specialError00100) {
isAlert = false;
}
console.error('エラーが発生しました:', errorMessage);
if(isAlert) {
alert('エラーが発生しました');
}
// スピナーを消す
hideSpinner();
});
/**
* 「window.addEventListener('error', function (event) {」
* グローバルにcatchしてないjavascript例外を捕獲した時のeventオブジェクトより
* 詳細なデバッグ情報のあるerrorMessageを取得する。
*/
function getErrorMessageOnGlobalError(event) {
let errorMessage = `message : ${event.message} source : ${event.filename}:${event.lineno}:${event.colno}`;
if (event.error) {
if (event.error.stack) {
errorMessage += `stacktrace : ${event.error.stack}`;
}
}
return errorMessage;
}
Discussion