【自分用】

```wbsの図形描画するやつ

Sub DrawWBSArrows()

    ' ========================================================
    ' シートの1行目に「yyyy/mm」、2行目に日付（1,2,3...）が並んでいる想定
    ' G列を開始日列、H列を終了日列とする（変更する場合 Const を編集）
    ' ========================================================

    Dim ws As Worksheet
    Set ws = ActiveSheet

    Const COL_START_DATE As Long = 7 ' G列
    Const COL_END_DATE As Long = 8   ' H列
    Const HEADER_ROW As Long = 1 ' シートの1行目に「yyyy/mm」

    Dim row As Long, maxRow As Long
    Dim startStr As String, endStr As String
    Dim startDate As Date, endDate As Date
    Dim currentDate As Date
    Dim base As Long
    Dim firstCol As Long, lastCol As Long
    Dim topPos As Double, leftPos As Double, widthVal As Double, heightVal As Double
    Dim col As Long

    ' 最終行の判定（開始日・終了日のどちらか）
    maxRow = Application.WorksheetFunction.Max( _
        ws.Cells(ws.Rows.Count, COL_START_DATE).End(xlUp).row, _
        ws.Cells(ws.Rows.Count, COL_END_DATE).End(xlUp).row)

    ' 既存のWBS図形を削除
    Dim shp As Shape
    For Each shp In ws.Shapes
        If Left(shp.Name, 4) = "WBS_" Then shp.Delete
    Next shp

    ' 各行を処理
    For row = 2 To maxRow

        startStr = Trim(ws.Cells(row, COL_START_DATE).Value)
        endStr = Trim(ws.Cells(row, COL_END_DATE).Value)

        If Not IsDate(startStr) Or Not IsDate(endStr) Then GoTo SkipRow

        startDate = DateValue(startStr)
        endDate = DateValue(endStr)
        If startDate > endDate Then GoTo SkipRow

        firstCol = -1
        lastCol = -1

        ' 開始日～終了日までの日付を1日ずつ見て処理
        For currentDate = startDate To endDate
            Dim ym As String: ym = Format(currentDate, "yyyy/mm")
            Dim dayNum As Integer: dayNum = Day(currentDate)

            base = GetBaseCol(ws, HEADER_ROW, ym)
            If base = -1 Then GoTo SkipRow

            Dim currentCol As Long: currentCol = base + dayNum
            If firstCol = -1 Or currentCol < firstCol Then firstCol = currentCol
            If lastCol = -1 Or currentCol > lastCol Then lastCol = currentCol
        Next currentDate

        ' 座標とサイズを取得
        topPos = ws.Cells(row, firstCol).Top + 2
        leftPos = ws.Cells(row, firstCol).Left
        widthVal = ws.Cells(row, lastCol).Left + ws.Cells(row, lastCol).Width - leftPos
        heightVal = ws.Cells(row, firstCol).Height - 4

        ' 図形（五角形）を描画
        Dim arrowName As String: arrowName = "WBS_" & row
        With ws.Shapes.AddShape(msoShapePentagon, leftPos, topPos, widthVal, heightVal)
            .Name = arrowName
            .Fill.ForeColor.RGB = RGB(91, 155, 213)
            .Line.Visible = msoFalse
        End With

SkipRow:
    Next row

    MsgBox "WBSの矢印描画が完了しました！"

End Sub

' 年月（yyyy/mm）に対応するカレンダーベース列を返す関数
Function GetBaseCol(ws As Worksheet, headerRow As Long, ym As String) As Long
    Dim col As Long
    For col = 1 To ws.Cells(headerRow, ws.Columns.Count).End(xlToLeft).Column
        If Format(ws.Cells(headerRow, col).Value, "yyyy/mm") = ym Then
            GetBaseCol = col - 1 ' 左隣をbaseとして返す
            Exit Function
        End If
    Next col
    GetBaseCol = -1 ' 見つからない場合
End Function

```

```

Sub DrawWBSArrows()

    ' ========================================================
    ' シートの1行目に「yyyy/mm」、2行目に日付（1,2,3...）が並んでいる想定
    ' G列を開始日列、H列を終了日列とする（変更する場合 Const を編集）
    ' ========================================================

    Dim ws As Worksheet
    Set ws = ActiveSheet

    Const COL_START_DATE As Long = 7 ' G列
    Const COL_END_DATE As Long = 8   ' H列
    Const HEADER_ROW As Long = 1

    Dim row As Long, maxRow As Long
    Dim startStr As String, endStr As String
    Dim startDate As Date, endDate As Date
    Dim baseStart As Long, baseEnd As Long
    Dim startCol As Long, endCol As Long
    Dim topPos As Double, leftPos As Double, widthVal As Double, heightVal As Double

    ' 最終行取得
    With ws.UsedRange
        maxRow = .Row + .Rows.Count - 1
    End With

    ' 既存のWBS図形を削除
    Dim shp As Shape
    For Each shp In ws.Shapes
        If Left(shp.Name, 4) = "WBS_" Then shp.Delete
    Next shp

    ' 各行を処理
    For row = 2 To maxRow

        startStr = Trim(ws.Cells(row, COL_START_DATE).Value)
        endStr = Trim(ws.Cells(row, COL_END_DATE).Value)

        If Not IsDate(startStr) Or Not IsDate(endStr) Then GoTo SkipRow

        startDate = DateValue(startStr)
        endDate = DateValue(endStr)
        If startDate > endDate Then GoTo SkipRow

        ' base列を取得（yyyy/mm に対応する列の1つ左）
        baseStart = GetBaseCol(ws, HEADER_ROW, Format(startDate, "yyyy/mm"))
        baseEnd = GetBaseCol(ws, HEADER_ROW, Format(endDate, "yyyy/mm"))
        If baseStart = -1 Or baseEnd = -1 Then GoTo SkipRow

        ' 列番号 = base + 日
        startCol = baseStart + Day(startDate)
        endCol = baseEnd + Day(endDate)

        ' 座標とサイズを取得
        topPos = ws.Cells(row, startCol).Top + 2
        leftPos = ws.Cells(row, startCol).Left
        widthVal = ws.Cells(row, endCol).Left + ws.Cells(row, endCol).Width - leftPos
        heightVal = ws.Cells(row, startCol).Height - 4

        ' 図形（五角形）を描画
        Dim arrowName As String: arrowName = "WBS_" & row
        With ws.Shapes.AddShape(msoShapePentagon, leftPos, topPos, widthVal, heightVal)
            .Name = arrowName
            .Fill.ForeColor.RGB = RGB(91, 155, 213)
            .Line.Visible = msoFalse
        End With

SkipRow:
    Next row

    MsgBox "WBSの矢印描画が完了しました！"

End Sub

' ========================================================
' 年月（yyyy/mm）に対応するカレンダーベース列を返す関数
' ========================================================
Function GetBaseCol(ws As Worksheet, headerRow As Long, ym As String) As Long
    Dim col As Long
    For col = 1 To ws.Cells(headerRow, ws.Columns.Count).End(xlToLeft).Column
        If Format(ws.Cells(headerRow, col).Value, "yyyy/mm") = ym Then
            GetBaseCol = col - 1 ' 左隣をbaseとして返す
            Exit Function
        End If
    Next col
    GetBaseCol = -1 ' 見つからない場合
End Function

```

```
useEffect(() => {
  const fetchAllPages = async () => {
    const firstRes = await fetch(`/api/items?page=0&size=100`);
    const firstData = await firstRes.json();

    const totalPages = firstData.page.totalPages;
    const firstContent = firstData.content || [];

    const promises = [];
    for (let i = 1; i < totalPages; i++) {
      promises.push(fetch(`/api/items?page=${i}&size=100`).then(res => res.json()));
    }

    const restPages = await Promise.all(promises);
    const restContent = restPages.flatMap(page => page.content || []);

    setItems([...firstContent, ...restContent]);
  };

  fetchAllPages(); // ← useEffectの中で呼び出してる
}, []);
```