Как я могу создать таблицу, используя библиотеку реагировать-PDF для генерации отчета PDF?

Поскольку библиотека реагирует на pdf, предлагая некоторый ограниченный компонент и не позволяя отображать html-тег в реагировать на pdfrenderer.Так что у меня возникли проблемы с созданием таблицы с использованием этой библиотеки? Может ли кто-нибудь, пожалуйста, помогите мне, как я могу создать таблицу, используя эти компоненты библиотеки act-pdf?

4 ответа

вы можете использовать, как сказал @David-Kucsai в комментарии @david.kucsai / react-pdf-table

или без использования

небольшой пример

данные

      const data = {
  id: "5df3180a09ea16dc4b95f910",
  items: [
    {
      sr: 1,
      desc: "desc1",
      xyz: 5
    },
    {
      sr 2,
      desc: "desc2",
      xyz: 6
    }
  ],
};

app.js

      import React, { Component, Fragment } from 'react';
import {PDFViewer} from '@react-pdf/renderer'
import Table from './components/reports/Table'
import data from './data'


class App extends Component {
  render() {
    return (
        <Fragment>
            <PDFViewer width="1000" height="600">
                <Table data={data}/>
            </PDFViewer>
        </Fragment>
    );
  }
}

export default App;

Table.js

      import React from 'react';
import { Page, Document, StyleSheet } from '@react-pdf/renderer';
import ItemsTable from './ItemsTable'


const styles = StyleSheet.create({
    page: {
        fontSize: 11,
        flexDirection: 'column',
    }
  });
  
  const Table = ({data}) => (
            <Document>
                <Page size="A4" style={styles.page}>
                    // ...
                    <ItemsTable data={data} />
                    // ...
                </Page>
            </Document>
        );
  
  export default Table

ItemsTable.js

      import React from 'react';
import {View, StyleSheet } from '@react-pdf/renderer';


const styles = StyleSheet.create({
    tableContainer: {
        flexDirection: 'row',
        flexWrap: 'wrap'
    },
});

  const ItemsTable = ({data}) => (
    <View style={styles.tableContainer}>
        {/*<TableHeader />*/}
        <TableRow items={data.items} />
        {/*<TableFooter items={data.items} />*/}
    </View>
  );
  
  export default ItemsTable

TableRow.js

      import React, {Fragment} from 'react';
import {Text, View, StyleSheet } from '@react-pdf/renderer';


const styles = StyleSheet.create({
    row: {
        flexDirection: 'row',
        alignItems: 'center',
    },
    description: {
        width: '60%',
    },
    xyz: {
        width: '40%',
    }
  });


const TableRow = ({items}) => {
    const rows = items.map( item => 
        <View style={styles.row} key={item.sr.toString()}>
            <Text style={styles.description}>{item.desc}</Text>
            <Text style={styles.xyz}>{item.xyz}</Text>
        </View>
    )
    return (<Fragment>{rows}</Fragment> )
};
  
export default TableRow

для получения дополнительной информации проверьте создание динамических счетов-фактур в формате PDF с помощью React и React-PDF.

Спасибо Яшу за подробный ответ. Это то, что я в конечном итоге создал, увидев ваш пример.

Основной трюк для создания «таблицы» заключается в использовании столбцов фиксированной ширины в каждой строке.

Примечание . Сделайте родительский контейнер (в данном случае таблица), если вы хотите, чтобы ваши строки превышали 100% без переполнения/роста родителя. Я бы по-прежнему рекомендовал вам попытаться увеличить общую ширину до 100%, но пример ниже показывает обратное.

      import { StyleSheet, Text, View } from '@react-pdf/renderer'
import PropTypes from 'prop-types'

const styles = StyleSheet.create({
  table: {
    width: '100%',
  },
  row: {
    display: 'flex',
    flexDirection: 'row',
    borderTop: '1px solid #EEE',
    paddingTop: 8,
    paddingBottom: 8,
  },
  header: {
    borderTop: 'none',
  },
  bold: {
    fontWeight: 'bold',
  },
  // So Declarative and unDRY 
  row1: {
    width: '27%',
  },
  row2: {
    width: '15%',
  },
  row3: {
    width: '15%',
  },
  row4: {
    width: '20%',
  },
  row5: {
    width: '27%',
  },
})

const ReportTable = ({ data, maximumDays }) => {
  return (
    <View style={styles.table}>
      <View style={[styles.row, styles.bold, styles.header]}>
        <Text style={styles.row1}>Name</Text>
        <Text style={styles.row2}>Start Date</Text>
        <Text style={styles.row3}>End Date</Text>
        <Text style={styles.row4}>Days</Text>
        <Text style={styles.row5}>Info</Text>
      </View>
      {data.map((row, i) => (
        <View key={i} style={styles.row} wrap={false}>
          <Text style={styles.row1}>
            <Text style={styles.bold}>{row.lastName}</Text>, {row.firstName}
          </Text>
          <Text style={styles.row2}>{row.startDate}</Text>
          <Text style={styles.row3}>{row.endDate}</Text>
          <Text style={styles.row4}>
            <Text style={styles.bold}>{row.days}</Text> of{' '}
            {maximumDays}
          </Text>
          <Text style={styles.row5}>{row.info}</Text>
        </View>
      ))}
    </View>
  )
}

ReportTable.propTypes = {
  data: PropTypes.array.isRequired,
  maximumDays: PropTypes.number.isRequired,
}

export default ReportTable

простой ответ таблицы здесь:витрина

Код:

          /* eslint-disable react-hooks/exhaustive-deps */
import React, { Fragment, useEffect, useState } from "react";
import { View, StyleSheet, Text } from "@react-pdf/renderer";

export default function Table({ data }) {

    const [tableData, setTableData] = useState();
    const styles = StyleSheet.create({
        rowView: {
            display: 'flex', flexDirection: 'row', borderTop: '1px solid #EEE', paddingTop: 8, paddingBottom: 8, textAlign: "center"
        }
    });

    useEffect(() => {
        if (data !== undefined) setTableData(data);
    }, []);

    return (
        <>
            {tableData &&
                (
                    <Fragment>
                        <View style={styles.rowView}>
                            {tableData["column"].map((c) => <Text style={{
                                width: `${100 / tableData["column"].length}%`
                            }}>{c}</Text>)}
                        </View>
                        {tableData["data"].map((rowData) => <>
                            <View style={styles.rowView}>
                                {tableData["column"].map((c) =>
                                    <Text style={{ width: `${100 / tableData["column"].length}%` }}>{rowData[c]}</Text>
                                )}
                            </View>
                        </>)}
                    </Fragment>
                )}
        </>

    )
}

формат данных:

      {
    "column": [
        "price",
        "email",
        "time"
    ],
    "data": [
        {
            "price": "",
            "email": "",
            "time": ""
        },
        {
            "price": "",
            "email": "",
            "time": ""
        }
    ]
}

таблица автоматически заполняется в зависимости от количества столбцов и автоматических размеров, чтобы занять всю страницу. просто не забудьте использовать имена столбцов в качестве ключей данных

      function checkStrEmpty(str) {
return !(str && str.length > 1 && str.split(" ").join("").length > 0);
}

import { Text, View, StyleSheet } from "@react-pdf/renderer";
import React from "react";
 
function CustomTablePDF(props) {
const { fields = [], data = [] } = props;
let tableCol = {
    borderStyle: BORDER_STYLE,
    borderColor: BORDER_COLOR,
    borderBottomColor: "#000",
    borderWidth: 1,
    borderLeftWidth: 0,
    borderTopWidth: 0
};
return (
    <View style={styles.table}>
        <View style={[styles.tableRow, styles.headerBg]}>
            {fields.map((_item, _idx) => (
                <View
                    key={_idx}
                    style={[tableCol, { width: _item.width + "%" }]}
                >
                    <Text
                        style={[
                            styles.tableCellHeader,
                            { textAlign: "center" }
                        ]}
                    >
                        {_item.title}
                    </Text>
                </View>
            ))}
        </View>

        {data.map(
            (item, idx) =>
                item && (
                    <View key={idx} style={styles.tableRow}>
                        {fields.map((_item, _idx) => {
                            let val = item[_item.value] || "";
                            let value_alt =
                                (_item.value_alt &&
                                    item[_item.value_alt]) ||
                                "";

                            if (_item.custom) {
                                return (
                                    <View
                                        key={_idx}
                                        style={[
                                            tableCol,
                                            { width: _item.width + "%" }
                                        ]}
                                    >
                                        <Text
                                            style={[
                                                styles.tableCell,
                                                item.style ? item.style : {}
                                            ]}
                                        >
                                            {_item.component(item)}
                                        </Text>
                                    </View>
                                );
                            } else {
                                return (
                                    <View
                                        style={[
                                            styles.tableCol,
                                            { width: _item.width + "%" }
                                        ]}
                                    >
                                        <Text
                                            style={[
                                                styles.tableCell,
                                                item.style ? item.style : {}
                                            ]}
                                        >
                                            {checkStrEmpty(val)
                                                ? value_alt
                                                : val || "-"}
                                        </Text>
                                    </View>
                                );
                            }
                        })}
                    </View>
                )
        )}
    </View>
);
}

const BORDER_COLOR = "#000";
const BORDER_STYLE = "solid";
const styles = StyleSheet.create({
headerBg: {
    backgroundColor: "#aaa"
},
table: {
    display: "table",
    width: "auto",
    borderStyle: BORDER_STYLE,
    borderColor: BORDER_COLOR,
    borderWidth: 1
    // borderRightWidth: 0,
    // borderBottomWidth: 0,
},
tableRow: {
    margin: "auto",
    flexDirection: "row"
},

tableCellHeader: {
    margin: 2,
    fontSize: 13,
    fontWeight: "bold"
    // fontFamily: "CustomRoboto",
},
tableCell: {
    margin: 2,
    fontSize: 12
    // fontFamily: "CustomRoboto",
},
textCenter: {
    textAlign: "center"
}
});

export default CustomTablePDF;

используйте такой компонент

      const fields = [
        {
            title: " Agent Name",
            custom: true,
            component: (item) => `${item.agent_name}`,
            width: "30"
        },
        {
            title: " Policy No",
            custom: true,
            component: (item) => `${item.policy_no}`,
            width: "35"
        },
        {
            title: "Policy Class",
            value: 'policy_class',
            width: "20"
        },
        {
            title: "Amount",
            custom: true,
            style: { textAlign: "right" },
            className: "text-right",
            component: (item) =>`${formatNumber(item.contribution)}`,
            width: "15"
        }
    ];
   
<CustomTablePDF fields={fields} data={details} />
      
Другие вопросы по тегам