2022改訂教育課程が導入されてから科目が増え、それに伴って評価計画書も毎学期ごとに新しく作成しなければならなくなった。
問題は、評価計画書には各単元別の達成基準や達成水準などをすべて記載しなければならないという形式的な手続きが必要だという点である。
しかしこうした基準は、教師が一から作成するのではなく、単純にコピー&ペーストしているだけだ。
そこで、該当内容をテーブルとして整理したうえで、Excel やスプレッドシートの FILTER と TEXTJOIN 関数を使って自動的に結合してみることにした。
1. 達成水準データベースを作る
各選択教科ごとの達成水準は、下記の KICE 学生評価支援ポータルで取得できる。
上部メニューの[初/中/高] -> [教育課程達成基準] -> [達成基準資料室] で検索してダウンロードすればよい。
例えば「世界市民と地理」の達成水準を見ると、次のようになっている。
問題は、このような達成基準が少ないものでも 15 個ほどあり、各達成基準ごとに達成水準をコピーして A〜E までまとめなければならないということだ。
では、この資料をテーブルにしてみよう。

まず hwp 形式のファイルをhwpx ファイルに変換する。
hwpx ファイルは内部ファイル構造を XML データとして保存しているため、他のプログラムで内部をパースできるようになる。

そして Python を使って hwpx 内部のテーブルを抽出してみる。
以下のコードは、もちろん chatGPT 兄貴の助けを借りて作成した。
hwpx ファイルは zip + xml 構造なので、Python で内部の xml を読み取り、テーブルを抽出できる。
// 이 코드는 생성형 AI를 이용해 제작한 코드입니다.
import zipfile
import xml.etree.ElementTree as ET
from openpyxl import Workbook
hwpx_path = "사회과 선택과목 성취수준 현장 보급본.hwpx"
xlsx_path = "output.xlsx"
def tag_name(elem):
return elem.tag.split("}")[-1]
def collect_text(node):
texts = []
# tc 내부에 중첩 tbl이 있으면 그 하위 텍스트는 제외한다.
stack = [node]
while stack:
cur = stack.pop()
if cur is not node and tag_name(cur) == "tbl":
continue
if tag_name(cur) == "t" and cur.text:
t = cur.text.strip()
if t:
texts.append(t)
children = list(cur)
stack.extend(reversed(children))
return "\n".join(texts)
def is_title_like(text):
if not text:
return False
compact = text.replace(" ", "")
# 표 전체 내용을 붙여 놓은 긴 문장은 제목으로 취급하지 않는다.
if len(text) > 80:
return False
# 표 헤더/본문 키워드가 포함되면 제목 행으로 넣지 않는다.
if "성취기준" in compact and "성취수준" in compact:
return False
return True
wb = Workbook()
ws = wb.active
ws.title = "tables"
saved_table_count = 0
current_row = 1
with zipfile.ZipFile(hwpx_path, "r") as z:
section_files = sorted(
name for name in z.namelist()
if name.startswith("Contents/section") and name.endswith(".xml")
)
for section_file in section_files:
xml_data = z.read(section_file)
root = ET.fromstring(xml_data)
elems = list(root.iter())
for i, elem in enumerate(elems):
if tag_name(elem) != "tbl":
continue
tbl = elem
prev_text = ""
for j in range(i - 1, -1, -1):
if tag_name(elems[j]) != "p":
continue
texts = []
for x in elems[j].iter():
if tag_name(x) == "t" and x.text:
t = x.text.strip()
if t:
texts.append(t)
candidate = " ".join(texts)
if not candidate:
continue
if is_title_like(candidate):
prev_text = candidate
break
table_rows = []
for tr in tbl:
if tag_name(tr) != "tr":
continue
row_values = []
for tc in tr:
if tag_name(tc) != "tc":
continue
row_values.append(collect_text(tc))
if row_values:
table_rows.append(row_values)
if not table_rows:
continue
preview_text = "".join(table_rows[0])
# 1행 1셀 같은 요약성/오검출 표는 제외한다.
has_enough_shape = len(table_rows) >= 2 and any(len(r) >= 2 for r in table_rows)
if "성취기준별" in preview_text and "성취수준" in preview_text and has_enough_shape:
saved_table_count += 1
table_title = prev_text if is_title_like(prev_text) else ""
for row_values in table_rows:
# 1열에는 표 제목을 두고, 실제 표 데이터는 오른쪽(2열부터) 배치한다.
ws.cell(row=current_row, column=1, value=table_title)
first_value = row_values[0].strip() if row_values and isinstance(row_values[0], str) else ""
start_col = 3 if first_value in {"B", "C", "D", "E"} else 2
for col_idx, value in enumerate(row_values, start=start_col):
ws.cell(row=current_row, column=col_idx, value=value)
# 오른쪽으로 밀린(B/C/D/E) 행은 표의 첫 번째 열(2열)을 바로 윗행 값으로 채운다.
if start_col == 3 and current_row > 1:
ws.cell(row=current_row, column=2, value=ws.cell(row=current_row - 1, column=2).value)
current_row += 1
# 표 사이 한 줄 띄우기
current_row += 2
if saved_table_count == 0:
ws["A1"] = "조건에 맞는 표를 찾지 못했습니다."
wb.save(xlsx_path)
print(f"완료: {saved_table_count}개 표를 하나의 시트에 저장")こうすると、内部テーブルが次のように抽出される。
それでもうまく抽出されない表がある場合は、手作業でデータを少しだけ整形しよう。

単純に Excel でフィルターと区切り位置(テキスト分割)を使って、それぞれ達成基準コード、内容、達成基準別の達成水準を分離した。
これを正規化すれば性能は上がるだろうが、人が確認するにはかえってわかりづらくなるので、そのまま重複したカラムの状態にしておくことにした。
そしてここまで作ってみると、いっそデータベースの公開請求をすればよかったのでは、という気もしてくる。
2. スプレッドシートを作る
一般的な学校では、評価計画に各週に対応する達成コードと達成基準を入れる。
そこで、月ごとに達成コードだけ選べば自動的に埋め込まれるようにすれば、評価計画の入力がかなり楽になるだろうと考えた。
スプレッドシートは filter と unique 関数を使って、入力しようとする科目・単元・達成コードを組み合わせて作成した。
もし難しく感じるなら、AI と一緒に作ってみることをおすすめしたい。

最初のタブでは、月、週、単元名、達成基準コードを入力すると、一番右側でコピー&ペーストするだけでよいように作ってみた。
中央の緑色のボックス部分は、自分が入力した達成基準を確認するために作っておいたものだ。
このように選択さえすれば、単元別達成基準および達成水準、学期単位の達成水準がすべて完成するようにしてある。

実のところ、一般的な教科ではすべての達成基準を評価計画に入れるので、そのまま全部突っ込んでしまっても構わないが、教育課程の再構成を考慮して作成した。
単に A〜E をすべて結合してくれるシートも一つ入れてみようかと悩んでいるところだ。
また、パフォーマンス評価用のシートも一つ作ってみた。

自分がパフォーマンス評価に入れたい達成基準コードを入力すると、評価計画書に入れられるように A〜E 水準をすべて結合してくれる。
私たちが悩むべきなのは、コピー&ペーストではなく、実質的にどのような評価が行われるべきかという点である。
3. 使ってみた感想

残念ながら多くの教師たちは、評価計画に多くの時間を注ぎ込んでいるにもかかわらず、教室にいる誰一人として達成水準の文章に関心を持たない。
評価計画そのものよりも、評価計画に基づいて実際に行われる評価そのものが重要だからだ。
達成基準を評価基準に書き込むようになってから卒業した人たちに、達成基準が何だったのか尋ねたとしても、誰一人として覚えていないだろうと断言できる。
だから、評価基準にこうした文章を入れることは、意味のない形式的な行為に過ぎないと言えるだろう。
学校で行われている教育の現場は、達成コードや達成基準といった静的なものではなく、動的なものである。
私たちは評価計画という公文書の完成度よりも、評価そのものの質的な問題について考える時間が、もっと必要なのではないかと思う。
おそらく、きちんとした使用レビューは、実際に使ってみたあとの 7〜8 月以降にしか書けないだろう。
隣の席の先生にこのスプレッドシートを共有したところ、今すぐにでも 2 学期の評価計画を作れそうだと喜んでおられた。
きっと多くの人の役に立つのではないかと思う。




댓글을 불러오는 중...