• #tax-assistant
  • #ui
  • #vue
  • #ocr
開発未分類

レシート一覧にソート機能を追加してOCRエラーを発見しやすくする

結論

レシート一覧の「日」と「ファイル名」にソート機能を追加した。ファイル名順にソートすると、日付のOCR誤読を視覚的に発見しやすくなる。

ソート機能を追加した読み取り一覧

上の例では、ファイル名が連番(0001〜0018)なのに、14番目(0016.jpg)だけ日付が「13」になっている。前後の行の日付は22〜23日なので、明らかにOCRの誤読だとわかる。

前提条件

この手法が有効なのは、以下の条件を満たす場合である。

  • 紙の伝票を日付順に積み上げてスキャンしている
  • スキャナーが連番ファイル名を付与している(例:20240815_0249_0001.jpg〜)
  • OCRで読み取った日付がYYYY/MM/DD形式で保存されている

この条件下では、ファイル名の連番と日付の昇順が一致するはずなので、一致しない箇所=OCR誤読の可能性が高い。

背景

税務アシスタントでは、スキャンしたレシートをOCRで読み取りデータ化している。OCRは完璧ではないため、日付の誤読が発生することがある。

従来の読み取り一覧では、ファイル名しか表示されていなかった。

改善前の読み取り一覧

これでは、日付が正しく読み取れているかを確認するには、1件ずつ詳細画面を開く必要があった。

実装内容

1. 日付の「日」をファイル名の前に表示

ファイル名だけでなく、OCRで読み取った日付の「日」部分を表示するようにした。日付はYYYY/MM/DD形式で保存されているため、末尾2桁を切り出すことで「日」を取得している。

日付を追加した読み取り一覧

<span class="item-day">
  {{ ((item as Record<string, unknown>)['日付'] as string)?.slice(-2) || '-' }}
</span>
<span class="item-filename">{{ item.file_name }}</span>

2. ヘッダーにソート機能を追加

「日」と「ファイル名」のヘッダーをクリックすると、それぞれの列でソートできるようにした。

// ソート状態
type SortColumn = 'day' | 'file_name' | null
const sortColumn = ref<SortColumn>(null)
const sortDirection = ref<'asc' | 'desc'>('asc')

// 元のインデックスを保持したソート済みアイテム
const sortedItemsWithIndex = computed(() => {
  const itemsWithIndex = props.items.map((item, index) => ({ item, originalIndex: index }))

  if (!sortColumn.value) return itemsWithIndex

  const col = sortColumn.value
  const dir = sortDirection.value === 'asc' ? 1 : -1

  return [...itemsWithIndex].sort((a, b) => {
    if (col === 'day') {
      const dateA = (a.item as Record<string, unknown>)['日付'] as string || ''
      const dateB = (b.item as Record<string, unknown>)['日付'] as string || ''
      return dateA.localeCompare(dateB) * dir
    } else if (col === 'file_name') {
      return a.item.file_name.localeCompare(b.item.file_name) * dir
    }
    return 0
  })
})

ポイントは、ソート後もoriginalIndex(元配列でのインデックス)を保持していること。親コンポーネントは元配列のインデックスで選択状態を管理しているため、ソートしても選択中のアイテムが維持される。

3. ヘッダーの位置をデータ行と揃える

ヘッダーの「日」「ファイル名」の位置が実際のデータ行と揃うようにスペーサーを追加した。

<div class="panel-title">
  <span class="header-dot-spacer" />
  <span class="header-no-spacer" />
  <span class="sort-header header-day" @click="toggleSort('day')">
    <span class="sort-icon">↕</span>
  </span>
  <span class="sort-header header-filename" @click="toggleSort('file_name')">
    ファイル名
    <span class="sort-icon">↕</span>
  </span>
</div>

まとめ

  • レシート一覧に「日」列とソート機能を追加した
  • ファイル名順にソートすることで、日付のOCR誤読を視覚的に発見できる
  • 日付順に積み上げてスキャンした伝票であれば、ファイル名の連番と日付が対応するはず
  • 対応していない箇所は、OCRの誤読の可能性が高い