Как я могу создать таблицу, используя библиотеку реагировать-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.
Спасибо Яшу за подробный ответ. Это то, что я в конечном итоге создал, увидев ваш пример.
Основной трюк для создания «таблицы» заключается в использовании столбцов фиксированной ширины в каждой строке.
Примечание . Сделайте родительский контейнер
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} />