ReoGrid ReoGrid Web

選択とイベント

セル選択の操作とイベント購読の方法を説明します。

Live Demo

選択範囲の操作

worksheet.selection は SelectionHandle を返します — アクティブな選択範囲に対する薄いファサードで、読み取り(bounds、アクティブセル、range ビュー)と変更(スタイル操作、値、移動)の両方を提供します。

const ws = grid.worksheet

// 選択範囲を移動 — 数値座標
ws.selection.moveTo(0, 0, 4, 3) // topRow, leftColumn, bottomRow, rightColumn

// または A1 形式のアドレス
ws.selection.moveTo('A1:D5')

// 現在の bounds を読み取り(選択がない場合は null)
const b = ws.selection.bounds
if (b) {
  console.log(b.topRow, b.leftColumn, b.bottomRow, b.rightColumn)
}

// 選択範囲内のアクティブ(フォーカス中)セル
const active = ws.selection.activeCell // { row, column } | null

// 選択範囲を RangeHandle に変換してフルレンジ操作を実行
const range = ws.selection.range
range?.setBold().setBackgroundColor('#fef3c7')

// 指定セルがアクティブセルか確認
const isActive = ws.isActiveCell(0, 0)

内部の SelectionRange ステートマシンがハンドルを支えていますが、これは @internal であり公開 API ではありません。常に worksheet.selection を使用してください。


複数範囲の選択

v1.6.0 から、Ctrl(macOS では Cmd。macOS の Ctrl+クリックは右クリックのため)を押しながらクリック・ドラッグすると、選択を置き換えずに範囲を追加します。セルでも行・列ヘッダーでも同じです。両エディションで利用できます。

操作結果
Ctrl/Cmd + クリック・ドラッグ範囲を追加し、それがアクティブになる
通常のクリック、矢印キー単一範囲に戻る
Shift + クリック、Shift + 矢印最新の範囲を広げ、他の範囲は保つ

「選択範囲」に対する操作はすべての範囲に効きます。Delete は 1 手の undo ですべての範囲を消し、書式はすべての範囲に適用され、Ctrl+クリックした列の境界をダブルクリックするとその各列(間の列は対象外)が自動調整されます。

const ws = grid.worksheet

ws.selection.moveTo('A1:B2')
ws.selection.add('D4:E6')      // 2 つの範囲を選択 — Ctrl+クリックの API 版

ws.selection.count              // 2
ws.selection.ranges             // RangeHandle[] — 最後がアクティブな範囲

// ユーザーが選択したすべてに操作を適用する
ws.selection.ranges.forEach(r => r.setBold())

bounds / range / activeCell / moveTo は従来どおり単一範囲を指します(最後に選択されたアクティブな範囲)。単一範囲の選択でも ranges は 1 要素を返すため、「ユーザーが選択したもの」に対して操作するなら ranges が安全です。

コピーとカット

コピーは Excel の規則に従います。範囲が整列している(同じ列で縦に並ぶ、または同じ行で横に並ぶ)場合のみ 1 ブロックとして運ばれます(値・スタイル・表示形式を含む)。それ以外は拒否され、Excel と同じ説明がセル上に表示されます。

複数範囲を選択している間

フィルハンドルとドラッグ移動は無効になり、選択済みのセルを Ctrl+クリックしても解除ではなく追加になります。

複数範囲の選択デモで実際に試せます。


イベント購読

すべてのイベントメソッドは、購読解除関数を返します。

選択変更

// リスナーは選択範囲 — { row, col, rows, columns }
//(左上セル + 行数・列数)— または選択がない場合は null を受け取ります
const unsub = ws.onSelectionChange((range) => {
  if (range) {
    const col = String.fromCharCode(65 + range.col)
    console.log(`Selected: ${col}${range.row + 1} (${range.rows} x ${range.columns})`)
  }
})

// 購読解除
unsub()

v1.6.0 から、第 2 引数がすべての選択範囲を列挙するため、リスナー側で複数範囲の選択に対応できます。第 1 引数は従来どおりアクティブな範囲なので、既存の 1 引数のリスナーは影響を受けません。

ws.onSelectionChange((range, ranges) => {
  console.log(`${ranges.length} 個の範囲を選択中`)
})

セル値変更

ws.onCellValueChange(({ row, column }) => {
  console.log(`Cell changed: row=${row}, col=${column}`)
  const value = ws.getCellInput(row, column)
  console.log('New value:', value)
})

コンテキストメニュー

ws.onContextMenu((event) => {
  // event.area: 'cell' | 'row-header' | 'column-header' | 'corner'
  // event.row, event.column: クリック位置
  // event.originalEvent: ブラウザの MouseEvent
  console.log('Context menu:', event.area, event.row, event.column)
})

ビューポートサイズ変更

ws.onViewportSizeChange(({ width, height }) => {
  console.log(`Viewport resized: ${width} x ${height}`)
})

スクロール変更

ws.onScrollChange(({ x, y }) => {
  console.log(`Scroll position: x=${x}, y=${y}`)
})

構造変更(行・列の挿入/削除)

ws.onStructureChange(() => {
  console.log('Grid structure changed')
})

画像変更

ws.onImagesChange((images) => {
  console.log('Images updated:', images.length)
})

保護セルの編集試行

ws.onProtectedCellEdit(({ row, column }) => {
  alert(`セル (${row}, ${column}) は保護されています`)
})

スクロール操作

// スクロール位置の取得
const offset = ws.getScrollOffset()
console.log(offset.x, offset.y)

// スクロール位置の設定
ws.setScrollOffset(100, 200)

// スクロールコンテンツのサイズ
const size = ws.getScrollContentSize()
console.log(size.width, size.height)

// ビューポートサイズ
const bodyWidth = ws.getBodyViewportWidth()
const bodyHeight = ws.getBodyViewportHeight()

ヒットテスト

画面座標からセル位置を特定できます。

// 簡易ヒットテスト
const cell = ws.getCellFromPoint(x, y)
if (cell) {
  console.log(`Row: ${cell.row}, Column: ${cell.column}`)
}

// 詳細ヒットテスト
const result = ws.hitTest(x, y)

x / y は 100% のシート px で表した canvas 上の座標です。シートを拡大・縮小している場合(v1.7.0)は、CSS px のポインタ位置を先に ws.getZoom() で割ってください。


セル矩形の取得

// セルの画面上の矩形
const rect = ws.getCellRect(0, 0)
// { x, y, width, height }

// 範囲の画面上の矩形
const rangeRect = ws.getRangeRect(0, 0, 4, 3)

矩形は 100% のシート px です。シートを拡大・縮小している場合(v1.7.0)は、ws.getZoom() を掛けると canvas 上の CSS px になります(独自の要素を重ねる場合を参照)。


使用例:ツールバー連携

import { useState, useEffect } from 'react'

function Toolbar({ worksheet }) {
  const [cellRef, setCellRef] = useState('A1')
  const [cellValue, setCellValue] = useState('')

  useEffect(() => {
    if (!worksheet) return

    return worksheet.onSelectionChange((range) => {
      if (range) {
        const col = String.fromCharCode(65 + range.col)
        setCellRef(`${col}${range.row + 1}`)
        setCellValue(worksheet.getCellInput(range.row, range.col) || '')
      }
    })
  }, [worksheet])

  return (
    <div>
      <span>{cellRef}</span>
      <input
        value={cellValue}
        onChange={(e) => {
          setCellValue(e.target.value)
        }}
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            const active = worksheet.selection.activeCell
            if (active) {
              worksheet.setCellInput(active.row, active.column, cellValue)
            }
          }
        }}
      />
    </div>
  )
}
このページは役に立ちましたか?
ニュースレター

開発の最新情報をお届けします

新しいリリース・機能追加・お知らせをいち早く受け取るには、
メーリングリストにご登録ください。