mbrn / material-table

Datatable for React based on material-ui's table with additional features

Home Page:https://material-table.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Sorted table gets unsorted when clicked on a custom excel exporter

jamalbutt12322 opened this issue · comments

` import React, { useCallback, useEffect, useRef, useState } from "react";
import MaterialTable, { MTableToolbar } from "material-table";
import XLSX from "xlsx-js-style";
import { useSelector } from "react-redux";
import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined";
import * as Constants from "./constants";
import { selectUser } from "app/store/userSlice";
import moment from "moment";
import themesConfig from "app/configs/themesConfig";
import { downloadButtonReportButton } from "src/@mock-api/api/report-builder-api";
import BuilderDialog from "./BuilderDialog";

function ReportTable(props) {

const user = useSelector(selectUser);

const filtersValue = useSelector(
  ({ reportBuilderApp }) => reportBuilderApp.reportFilters
);

const [exportLevel, setExportevel] = React.useState(null);
const [open, setOpen] = React.useState(false);

//separating levels from labels....
const levelsOnly = Object.keys(filtersValue.levels)
  .filter((key) => !key.includes("label"))
  .map((key) => filtersValue.levels[key]);
const [levels, setLevels] = useState(levelsOnly);

const [levelTitle, setLevelTitle] = useState(
  levels.map((e, i) => filtersValue.levels[`level${i + 1}_label`]).join(" > ")
);

const [measureTitle, setMeasureTitle] = useState(
  filtersValue?.show?.measure?.label + ` (${filtersValue?.show?.dataType})`
);

const excelDownloader = useCallback(() => {
  
  setOpen(true);
}, []);
const handleChange = (event) => {
  setExportevel(event.target.value);
};


console.log("reporttable columns: ", columns);

const generateExcel = () => {
  const wb = XLSX.utils.book_new();
  const measureFormat = (param) => {
    return {
      v: param,
      t: "s",
      s: {
        font: { name: "Calibri", sz: 10 },
        alignment: { horizontal: "center" },
      },
    };
  };

  const rowFormat = (param) => {
    return { v: param, t: "s", s: { font: { name: "Calibri", sz: 10 } } };
  };
  const colFormat = (param) => {
    return {
      v: param,
      t: "s",
      s: { font: { bold: true, name: "Calibri", sz: 10 } },
    };
  };

  let selectedMeasureName = [measureFormat(filtersValue.show.measure.label)];

  selectedMeasureName[0].v =
    selectedMeasureName[0].v + " (" + filtersValue.show.dataType + ") ";
  let temp_levels = levels;

  console.log("temp_levels:!: ", temp_levels);
  let header = [...levels.slice(0, exportLevel + 1), ...columnNames]?.map(
    (item) => {
      return colFormat(item);
    }
  );
  const currentState = tableRef?.current?.state;


  let rows = [exportLevel].map((level, i) => {
    return result
      .filter((e) => e.level == level)
      .map((row, i) => {
        // console.log(row)
        return [
          ...levels
            .slice(0, exportLevel + 1)
            .map((lvlName) => rowFormat(row[lvlName])),
          ...columnNames.map((e) => rowFormat(row[e])),
        ];
      });
  });
  rows = [selectedMeasureName, header].concat(rows.flat(1)); // adding element at 1st index of array

  // STEP 3: Create worksheet with rows; Add worksheet to workbook
  levels?.map((e, i) => {
    let newval = filtersValue.levels[`level${i + 1}_label`];

    rows[1][i] = newval;
  });
  console.log("rows: ", rows, "wb: ", wb, "levels: ", levels);
  const ws = XLSX.utils.aoa_to_sheet(rows);
  const merge = [{ s: { r: 0, c: 0 }, e: { r: 0, c: 10 } }];
  ws["!merges"] = merge;
  XLSX.utils.book_append_sheet(wb, ws, filtersValue.show.dataType);
  let date = new Date();
  let dateStr =
    date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
  // STEP 4: Write Excel file to browser
  XLSX.writeFile(wb, `${user.organization}_${dateStr}.xlsx`);
  setOpen(false);
};

function ColorLuminance(hex, lum) {
  // validate hex string
  hex = String(hex).replace(/[^0-9a-f]/gi, "");
  if (hex.length < 6) {
    hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
  }
  lum = lum || 0;

  // convert to decimal and change luminosity
  var rgb = "#",
    c,
    i;
  for (i = 0; i < 3; i++) {
    c = parseInt(hex.substr(i * 2, 2), 16);
    c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16);
    rgb += ("00" + c).substr(c.length);
  }

  return rgb;
}
var constPathColors = {};
let oldColor = themesConfig.default.palette.primary.main;
constPathColors[1] = oldColor;
for (let i = 2; i <= levels.length; i++) {
  let shade = oldColor;
  oldColor = ColorLuminance(shade, -0.4);
  constPathColors[i] = oldColor;
}
console.log("constPathColors: ", constPathColors);
const tableRef = useRef(null);

return (
  <>
    <div className="ReportTable" style={{ margin: "2%" }}>
      <MaterialTable
        tableRef={tableRef}
        columns={columns}
        data={result}

        parentChildData={(row, rows) =>
          rows.find(
            (a) =>
              a?.uniqueKey?.replaceAll(" ", "") ===
              row?.parentUniqueKey?.replaceAll(" ", "")
          )
        }
        
        options={{
          sorting: true,
          search: true,
          searchFieldAlignment: "right",
          searchAutoFocus: true,
          searchFieldVariant: "standard",
          filtering: false,
          paging: true,
          maxBodyHeight: 600,

          headerStyle: {
            position: "sticky",
            top: 0,
            whiteSpace: "nowrap",
            backgroundColor: themesConfig.defaultDark.palette.primary.dark,
            color: "#FFF",
          },

          pageSizeOptions: [5, 20, 50, 100].map((e) => e),
          pageSize: 5,
          paginationType: "stepped",
          showFirstLastPageButtons: false,
          paginationPosition: "bottom",
          exportButton: false,
          exportAllData: true,
          exportFileName: "TableData",
          addRowPosition: "first",
          actionsColumnIndex: -1,
          selection: false,
          showSelectAllCheckbox: false,
          showTextRowsSelected: false,
          selectionProps: (rowData) => ({
            disabled: rowData.age == null,
            // color:"primary"
          }),
          grouping: false,
          columnsButton: false,
          rowStyle: (rowData) => {
            if (
              rowData.tableData.isTreeExpanded === false &&
              rowData.tableData.path.length === 1
            ) {
              return {};
            }
            const rowBackgroundColor =
              constPathColors[rowData.tableData.path.length];
            return { backgroundColor: rowBackgroundColor };
          },
        }}
        actions={[
          {
            icon: () => (
              <div variant="outlined" color="warning">
                <FileDownloadOutlinedIcon />
              </div>
            ), // you can pass icon too
            onClick: () => excelDownloader(),
            isFreeAction: true,
          },
        ]}
        title={
          <>
            {levelTitle}
            
            {measureTitle}
          </>
        }
        components={{
          Toolbar: (props) => (
            <div>
              <MTableToolbar {...props} />
            </div>
          ),
        }}
      />
    </div>

    <BuilderDialog
      open={open}
      setOpen={setOpen}
      exportLevel={exportLevel}
      levels={levels}
      handleChange={handleChange}
      generateExcel={generateExcel}
    />
  </>
);

}

export default ReportTable;
`
When a user clicks on the icon (), it invokes the excelDownloader() function, which in turn opens a dialog box. Within the dialog box, the user can select the number of levels to generate the Excel report based on. The issue arises when the table is sorted, and the Excel downloader button is clicked, as it results in the data becoming unsorted. Is there any way to fix this while using material table?

commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You can reopen it if it required.