### javascriptで2次元配列の大きさを事前に設定したり、あとからサイズを変えることはできますか?vbaのredim的な考え方です

// 1次元配列の場合
const arr1 = new Array(10); // 長さ10の配列を作成(要素はundefined)
const arr2 = new Array(10).fill(0); // 長さ10、全要素を0で初期化
const arr2 = new Array(10).fill(""); // 長さ10、全要素を""で初期化

Dim arr1(10)


// 2次元配列の場合
const rows = 5;
const cols = 3;

// 方法1: Array.fromを使用
const matrix1 = Array.from({ length: rows }, () => new Array(cols).fill(0));

// 方法2: ループで作成
const matrix2 = [];
for (let i = 0; i < rows; i++) {
  matrix2[i] = new Array(cols).fill(0);
}

// 方法3: mapを使用
const matrix3 = new Array(rows).fill(null).map(() => new Array(cols).fill(0));

// 配列を大きくする
let arr = [1, 2, 3];
arr.length = 10; // 長さを10に拡張(新しい要素はundefined)

// 配列を小さくする
arr.length = 2; // [1, 2] になる(要素が削除される)

// 2次元配列のサイズ変更例
function resizeMatrix(matrix, newRows, newCols, fillValue = 0) {
  // 行数を調整
  matrix.length = newRows;
  
  // 各行の列数を調整
  for (let i = 0; i < newRows; i++) {
    if (!matrix[i]) {
      matrix[i] = new Array(newCols).fill(fillValue);
    } else {
      matrix[i].length = newCols;
      // 新しく追加された要素を初期化
      for (let j = 0; j < newCols; j++) {
        if (matrix[i][j] === undefined) {
          matrix[i][j] = fillValue;
        }
      }
    }
  }
  
  return matrix;
}

// 使用例
let myMatrix = [[1, 2], [3, 4]];
console.log(myMatrix); // [[1, 2], [3, 4]]

resizeMatrix(myMatrix, 4, 3, 0);
console.log(myMatrix); // [[1, 2, 0], [3, 4, 0], [0, 0, 0], [0, 0, 0]]

###GAS でも同じことができますか?シートの範囲を配列に格納した後、行を追加して上書きする方法を知りたいです---

function addRowsToSheetData() {
  const sheet = SpreadsheetApp.getActiveSheet();
  
  // 1. シートの範囲を2次元配列として取得
  const range = sheet.getRange("A1:C5"); // 例:A1:C5の範囲
  let data = range.getValues(); // 2次元配列として取得
  
  console.log("元のデータ:", data);
  // [[値1, 値2, 値3], [値4, 値5, 値6], ...]
  
  // 2. 新しい行を追加
  const newRow1 = ["新データ1", "新データ2", "新データ3"];
  const newRow2 = ["新データ4", "新データ5", "新データ6"];
  
  data.push(newRow1); // 配列の末尾に追加
  data.push(newRow2);
  
  // または複数行を一度に追加
  // data = data.concat([newRow1, newRow2]);
  
  console.log("追加後のデータ:", data);
  
  // 3. 拡張した配列をシートに上書き
  const newRange = sheet.getRange(1, 1, data.length, data[0].length);
  newRange.setValues(data);
}

###より実用的------------------------
function insertRowsInMiddle() {
  const sheet = SpreadsheetApp.getActiveSheet();
  
  // 既存データを取得
  const range = sheet.getRange("A1:C10");
  let data = range.getValues();
  
  // 5行目と6行目の間に新しい行を挿入する場合
  const insertPosition = 5; // 0始まりなので、実際の6行目の位置
  const newRows = [
    ["挿入1", "挿入2", "挿入3"],
    ["挿入4", "挿入5", "挿入6"]
  ];
  
  // splice()で途中に挿入
  data.splice(insertPosition, 0, ...newRows);
  
  // シートに書き戻し
  const newRange = sheet.getRange(1, 1, data.length, data[0].length);
  newRange.setValues(data);
}
### const range = sheet.getRange("A1:C10"); を変数でできないですか?A1だけが固定で n行 m列を範囲として記述するには?

function getRangeWithVariables() {
  const sheet = SpreadsheetApp.getActiveSheet();
  
  const startRow = 1;    // 開始行(A1なら1)
  const startCol = 1;    // 開始列(Aなら1)
  const numRows = 10;    // 取得する行数
  const numCols = 3;     // 取得する列数
  
  // 方法1: getRange(行, 列, 行数, 列数)
  const range = sheet.getRange(startRow, startCol, numRows, numCols);
  const data = range.getValues();
  
  console.log(data);
}

function getRangeFromA1() {
  const sheet = SpreadsheetApp.getActiveSheet();
  
  const n = 10;  // 行数
  const m = 3;   // 列数
  
  // A1から n行 m列を取得
  const range = sheet.getRange(1, 1, n, m);
  const data = range.getValues();
  
  console.log(`A1から${n}行${m}列を取得:`, data);
}
### まとめ
function getRangeMethods() {
  const sheet = SpreadsheetApp.getActiveSheet();
  
  // 方法1: A1記法(文字列)
  const range1 = sheet.getRange("A1:C10");
  
  // 方法2: 行・列・行数・列数で指定(推奨)
  const range2 = sheet.getRange(1, 1, 10, 3);  // A1:C10と同じ
  
  // 方法3: 単一セル
  const range3 = sheet.getRange(1, 1);  // A1
  const range4 = sheet.getRange("A1");  // A1
  
  // 方法4: 行・列のみ(1セル)
  const range5 = sheet.getRange(5, 2);  // B5
  
  // 方法5: 変数を使った動的な範囲
  const startRow = 2;
  const startCol = 1;
  const rows = 5;
  const cols = 4;
  const range6 = sheet.getRange(startRow, startCol, rows, cols);  // A2:D6
}

### 配列は"" で満たすのが無難
ただし 四則演算をしたときに + だけは 文字列追加とされる
console.log("" + 10);   // "10" (文字列)← 注意!
console.log("" - 10);   // -10  (数値)

そのため 初期値 "" の場合は一度数字変換の必要
const value = data[i][j];
const numValue = Number(value);  // ""は0に、"123"は123に変換
const result = numValue + 100;

ただしこの時誤って "" ではなく 本当の文字列が入っていると NaNエラーになり
停止しないのでデバックが対品面倒になる
そこで 下記のように
 if (!isNaN(num)) で数字であることを確かめてから演算する

###NaNの回避
 let sum = 0;
  for (let i = 0; i < data.length; i++) {
    for (let j = 0; j < data[i].length; j++) {
      const num = Number(data[i][j]);
      
      if (!isNaN(num)) {
        sum += num;
      } else {
        console.log(`警告: 行${i+1}, 列${j+1}に数値以外のデータ: "${data[i][j]}"`);
      }
    }
  }

### const matrix1 = Array.from({ length: rows }, () => new Array(cols).fill(0));
の文法がわかりません 行がrowsはわかるのですが ()=>は何?先に1次元配列を作ってそれを拡張する意味ですか

// Array.from(配列的なもの, 各要素に対する関数)

// 例1:単純な配列生成
Array.from({ length: 5 })
// 結果: [undefined, undefined, undefined, undefined, undefined]

// 例2:各要素を変換
Array.from({ length: 5 }, (_, index) => index)
// 結果: [0, 1, 2, 3, 4]

// 例3:各要素を固定値に
Array.from({ length: 5 }, () => 100)
// 結果: [100, 100, 100, 100, 100]

###アロー関数 =>
// 従来の書き方(function)
Array.from({ length: 5 }, function() {
  return new Array(3).fill(0);
});

// アロー関数の書き方(=>)
Array.from({ length: 5 }, () => {
  return new Array(3).fill(0);
});

// さらに省略形(returnを省略)
Array.from({ length: 5 }, () => new Array(3).fill(0));

### => は引数なしの関数
// () => は「引数なし」
() => 何か

// (x) => は「引数1つ」
(x) => x * 2

// (x, y) => は「引数2つ」
(x, y) => x + y

const rows = 3;
const cols = 4;
const matrix = Array.from({ length: rows }, () => new Array(cols).fill(0));

// 実行の流れ:
// 1. Array.from({ length: 3 })
//    → 長さ3の配列を作る準備

// 2. 各要素(全3回)に対して () => new Array(cols).fill(0) を実行
//    1回目: new Array(4).fill(0) → [0, 0, 0, 0]
//    2回目: new Array(4).fill(0) → [0, 0, 0, 0]
//    3回目: new Array(4).fill(0) → [0, 0, 0, 0]

// 3. 結果
//    [[0, 0, 0, 0],
//     [0, 0, 0, 0],
//     [0, 0, 0, 0]]

###より詳しく
// 例1:各行を同じ配列で埋める(間違い!)
const bad = Array.from({ length: 3 }, () => [0, 0, 0]);
// これは正しく見えるが...

// 例2:インデックスを使う
const matrix2 = Array.from({ length: 3 }, (_, rowIndex) => {
  return new Array(4).fill(rowIndex);
});
// 結果:
// [[0, 0, 0, 0],
//  [1, 1, 1, 1],
//  [2, 2, 2, 2]]

// 例3:各セルに独自の値
const matrix3 = Array.from({ length: 3 }, (_, i) => {
  return Array.from({ length: 4 }, (_, j) => {
    return i * 4 + j;
  });
});
// 結果:
// [[0, 1, 2, 3],
//  [4, 5, 6, 7],
//  [8, 9, 10, 11]]


###他の書き方との比較
const rows = 3;
const cols = 4;

// 方法1: Array.from + アロー関数(推奨)
const m1 = Array.from({ length: rows }, () => new Array(cols).fill(0));

// 方法2: forループ(わかりやすい)
const m2 = [];
for (let i = 0; i < rows; i++) {
  m2[i] = new Array(cols).fill(0);
}

// 方法3: map(少し冗長)
const m3 = new Array(rows).fill(null).map(() => new Array(cols).fill(0));

// 方法4: スプレッド構文
const m4 = [...Array(rows)].map(() => new Array(cols).fill(0));

// 全て同じ結果
console.log(m1);
console.log(m2);
console.log(m3);
console.log(m4);