

Reactで以下のような機能を実装しようとしています．

HTML View

＜表の行数を指定するプルダウンリスト＞

セル１ | セル2 | セル３ | セル４ | セル5  
---|---|---|---|---  
１  | ２ | データ１ | データ２ | データ３  
２ | ３ | データ４ | データ５ | データ６  
  
上記のようなtable要素を生成しています．tableの行数は，プルダウンリストで指定し，動的に変化します．

このtableに入力された値を，csvで出力してEXCELで展開した際に，以下のような形式で表示されるようにしたいと考えています．

|  
---|---  
データ１ | データ４  
データ２ | データ５  
データ３ | データ６  
1→2 | 2→3  
  
現状，tableの並びでcsv出力は出来ているのですが，上記の形式で並び替えが出来ていません．  
ご教授頂けたら幸いです．

[code]

    import React, { useState, useEffect } from 'react';
    import saveAs from 'file-saver';
    import './App.css';
    import { encode } from 'iconv-lite'; // 追加
    
    function App() {
      const [element, setElement] = useState(1);
      const [rows, setRows] = useState(element + 1);
      const [tableData, setTableData] = useState([...Array(rows)].map(() => ['', '', '', '', '']));
      const [popupMessage, setPopupMessage] = useState('');
    
      const handleChangeElement = (e) => {
        const newElement = parseInt(e.target.value);
        setElement(newElement);
      };
    
      const handleCellValueChange = (e, rowIndex, colIndex) => {
        const value = e.target.value;
        // 正規表現を使用して半角数字のみを許可する
        const isNumber = /^\d*$/.test(value);
        if (isNumber) {
          const newTableData = [...tableData];
          newTableData[rowIndex][colIndex] = value;
          setTableData(newTableData);
        }
      };
    
      const handleChangeCell = (e, rowIndex, colIndex) => {
        const newData = [...tableData];
        newData[rowIndex][colIndex] = e.target.value;
        setTableData(newData);
      };
    
      const constructCSVData = () => {
        const csvRows = tableData.map((row) => {
          const concatenatedValue = `${row[0]}→${row[1]}`;
          const formattedRow = [concatenatedValue, ...row.slice(2)];
          return formattedRow.map((cell) => `"${cell}"`).join(',');
        });
        return csvRows.join('\n');
      };
    
    
    
      const handleExportCSV = () => {
        let hasEmptyFields = false;
        const emptyFields = [];
    
        tableData.slice(2).forEach((row, rowIndex) => {
          row.slice(2, 5).forEach((cell, colIndex) => {
            if (!cell) {
              hasEmptyFields = true;
              emptyFields.push(`行 ${rowIndex + 3} 列 ${colIndex + 3}`);
            }
          });
        });
    
        if (hasEmptyFields) {
          const message = `未入力項目があります: ${emptyFields.join(', ')}`;
          setPopupMessage(message);
          alert(message);
          return;
        }
    
        const csvContent = constructCSVData();
        const encodedContent = encode(csvContent, 'Shift_JIS'); // 文字エンコーディングをShift_JISに変更
        const csvData = new Blob([encodedContent], { type: 'text/csv;charset=Shift_JIS' }); // 文字エンコーディングをShift_JISに指定
        saveAs(csvData, 'data.csv');
      };
    
      useEffect(() => {
        setRows(element + 1);
        setTableData([...Array(element + 1)].map(() => ['', '', '', '', '']));
      }, [element]);
    
      return (
        <div>
          正答結線数を入力して下さい．
          <select name="element" value={element} onChange={handleChangeElement}>
            {[...Array(100).keys()].map((i) => (
              <option key={i} value={i + 1}>
                {i + 1}
              </option>
            ))}
          </select>
          {/*行の生成*/}
          <p>数値は半角で入力して下さい．</p>
          <table border="1">
            {[...Array(rows).keys()].map((i, index) => (
              <tr key={i} style={index === 0 ? { backgroundColor: 'gray' } : {}}>
                <td>
                  <input
                    type="text"
                    disabled={index === 0}
                    placeholder={index === 0 ? '何番から' : ''}
                    value={tableData[i][0]}
                    onChange={(e) => handleCellValueChange(e, i, 0)} // 入力値の検証を行う
                  />
                </td>
                <td>
                  <input
                    type="text"
                    disabled={index === 0}
                    placeholder={index === 0 ? '何番へ' : ''}
                    value={tableData[i][1]}
                    onChange={(e) => handleCellValueChange(e, i, 1)} // 入力値の検証を行う
                  />
                </td>
                <td>
                  {index === 0 ? (
                    '分野'
                  ) : (
                    <div>
                      <input
                        type="radio"
                        id={`field${i}1`}
                        name={`field${i}`}
                        value="同分野"
                        onChange={(e) => handleChangeCell(e, i, 2)}
                      />
                      <label htmlFor={`field${i}1`}>同分野</label>
                      <input
                        type="radio"
                        id={`field${i}2`}
                        name={`field${i}`}
                        value="別分野"
                        onChange={(e) => handleChangeCell(e, i, 2)}
                      />
                      <label htmlFor={`field${i}2`}>別分野</label>
                    </div>
                  )}
                </td>
                <td>
                  {index === 0 ? (
                    '記述'
                  ) : (
                    <div>
                      <input
                        type="radio"
                        id={`description${i}1`}
                        name={`description${i}`}
                        value="記述有り"
                        onChange={(e) => handleChangeCell(e, i, 3)}
                      />
                      <label htmlFor={`description${i}1`}>記述有り</label>
                      <input
                        type="radio"
                        id={`description${i}2`}
                        name={`description${i}`}
                        value="記述なし"
                        onChange={(e) => handleChangeCell(e, i, 3)}
                      />
                      <label htmlFor={`description${i}2`}>記述なし</label>
                    </div>
                  )}
                </td>
                <td>
                  {index === 0 ? (
                    '認知'
                  ) : (
                    <div>
                      <input
                        type="radio"
                        id={`knowledge${i}1`}
                        name={`knowledge${i}`}
                        value="知識"
                        onChange={(e) => handleChangeCell(e, i, 4)}
                      />
                      <label htmlFor={`knowledge${i}1`}>知識</label>
                      <input
                        type="radio"
                        id={`knowledge${i}2`}
                        name={`knowledge${i}`}
                        value="解釈"
                        onChange={(e) => handleChangeCell(e, i, 4)}
                      />
                      <label htmlFor={`knowledge${i}2`}>解釈</label>
                      <label htmlFor={`knowledge${i}3`}>分析</label>
    
                    </div>
                  )}
                </td>
              </tr>
            ))}
          </table>
    
          {/* 追加機能: CSV出力ボタン */}
          <button onClick={handleExportCSV}>CSVでマトリクスを出力</button>
    
        </div>
      );
    }
    export default App;
    
[/code]


CC BY-SA 4.0
2023-05-11T12:07:17.217
94822
2023-05-11T12:35:54.377
2023-05-11T12:35:54.377
3060
58256
question
reactjs
Reactによるcsvの出力形式について