rapid-spreadjs 1.0.171 → 1.0.173

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1523,16 +1523,26 @@ const BusinessUtils = {
1523
1523
  });
1524
1524
  }
1525
1525
  });
1526
- let serNum = 0;
1527
- hasValueRowsSer.forEach((rowIndex, index) => {
1528
- const curVal = sheet.getValue(rowIndex, 1);
1529
- // 检查第一个单元格的值是否包含非数字字符,有非数字字符的时候代表不填充序号
1530
- if (!/^(?!\d+$)[\u4e00-\u9fa5a-zA-Z0-9!@#$%^&*()_+[\]{};':",.\/?\\|-]+$/.test(curVal)) {
1531
- serNum++;
1526
+ // 禁用的时候,将所有的序号重新设置
1527
+ if (!isEnable) {
1528
+ rowCells.forEach((rowObj, index) => {
1532
1529
  // 设置序号列单元格的值(1、2、3...的格式)
1533
- sheet.setValue(rowIndex, 1, serNum);
1534
- }
1535
- });
1530
+ sheet.setValue(rowObj.rowSpan, 1, index + 1);
1531
+ });
1532
+ }
1533
+ // 启用的时候
1534
+ else {
1535
+ let serNum = 0;
1536
+ hasValueRowsSer.forEach((rowIndex, index) => {
1537
+ const curVal = sheet.getValue(rowIndex, 1);
1538
+ // 检查第一个单元格的值是否包含非数字字符,有非数字字符的时候代表不填充序号
1539
+ if (!/^(?!\d+$)[\u4e00-\u9fa5a-zA-Z0-9!@#$%^&*()_+[\]{};':",.\/?\\|-]+$/.test(curVal)) {
1540
+ serNum++;
1541
+ // 设置序号列单元格的值(1、2、3...的格式)
1542
+ sheet.setValue(rowIndex, 1, serNum);
1543
+ }
1544
+ });
1545
+ }
1536
1546
  hasValueRows.forEach((rowIndex, index) => {
1537
1547
  // 设置行可见
1538
1548
  sheet.setRowVisible(rowIndex, true);
@@ -1654,207 +1664,6 @@ const BusinessUtils = {
1654
1664
  }
1655
1665
  return { hasValueIndex: hasValueRows, noValueIndex: noValueRows };
1656
1666
  },
1657
- /**
1658
- * 动态加载行(动态显示数据行和序号值)
1659
- * @param GC GC对象
1660
- * @param spread 工作簿实例
1661
- * @param dynamicLoadRangeJson 动态加载的“试验结果”JSON数组范围,格式如:[{row: 1, col: 1, rowCount: 1, colCount: 1}]
1662
- * @param headerRangeHeight 表头区域总高度
1663
- * @param footerRangeHeight 表尾区域总高度
1664
- * @param remainingHeight 剩余高度(针对纵表情况,工作表总高度-表头和表尾总高度>=remainingHeight,空白行不显示;<remainingHeight,空白行显示)
1665
- * @param pageDir 页面方向(1:纵向、2:横向)
1666
- * @param blankRowCellValue 空白行单元格值,默认为:空白
1667
- * @returns 返回所有需要显示和隐藏的行索引结果对象,格式如:{hasValueIndex: [1, 2, 3], noValueIndex: [4, 5, 6]},hasValueIndex代表所有显示的行索引,noValueIndex代表所有隐藏的行索引
1668
- */
1669
- dynamicLoadRows_Backup: (GC, spread, dynamicLoadRangeJson, headerRangeHeight, footerRangeHeight, remainingHeight = 500, pageDir = 1, blankRowCellValue = '空白') => {
1670
- const sheet = spread.getActiveSheet();
1671
- // 暂停绘制
1672
- sheet.suspendPaint();
1673
- // 获取所有单元格对象
1674
- const cells = SheetUtils.getAllCellObjsByRanges(sheet, dynamicLoadRangeJson);
1675
- // 设置所有行可见,原因是:如果再次执行的时候,第一次隐藏的行没有还原
1676
- cells.forEach((item, index) => {
1677
- sheet.setRowVisible(item.row, true);
1678
- });
1679
- // 获取按照row分组后的数据,格式如:{"1":[{row: 1, col: 43, rowCount: 1, colCount: 24}]}
1680
- const cellsGroupByRow = rapidUtils.groupByJson(cells, 'row');
1681
- // 获取序号列的跨列数
1682
- let seqColSpanCount = null;
1683
- // 最终行索引Key对应的单元格对象集合(跨行的索引)
1684
- let rowCells = [];
1685
- rapidUtils.forEachJson(cellsGroupByRow, (cellItems, rowIndexKey, source) => {
1686
- if (seqColSpanCount == null) {
1687
- const seqSpans = sheet.getSpans(sheet.getCell(parseInt(rowIndexKey), 1));
1688
- seqColSpanCount = seqSpans[0].colCount;
1689
- }
1690
- // 得到序号列的跨行单元格对象
1691
- const seqColSpanObj = sheet.getSpans({ row: parseInt(rowIndexKey), col: 1, rowCount: cellItems[0].rowCount, colCount: seqColSpanCount })[0];
1692
- // 当前序号跨行单元格对应的所有单元格中是否有值
1693
- let curRowHasValue = false;
1694
- // 当前所有行索引
1695
- let curRowIndexs = [];
1696
- for (let i = 0; i < cellItems.length; i++) {
1697
- // 获取当前单元格对象
1698
- const cell = cellItems[i];
1699
- for (let j = cell.row; j < cell.row + cell.rowCount; j++) {
1700
- if (!curRowIndexs.some((x) => x == j)) {
1701
- curRowIndexs.push(j);
1702
- }
1703
- }
1704
- // 获取当前单元格的值
1705
- const cellValue = sheet.getValue(cell.row, cell.col);
1706
- // 验证是否有值
1707
- if (cellValue !== null &&
1708
- cellValue !== undefined &&
1709
- cellValue !== '' &&
1710
- cellValue !== '/' &&
1711
- !(cellValue instanceof GC.Spread.CalcEngine.CalcError)) {
1712
- curRowHasValue = true;
1713
- break;
1714
- }
1715
- }
1716
- let rowObjs = { row: parseInt(rowIndexKey), rows: curRowIndexs, cells: cellItems, hasValue: curRowHasValue };
1717
- if (!rowCells.some((x) => x.rowSpan == seqColSpanObj.row)) {
1718
- rowCells.push({
1719
- rowSpan: seqColSpanObj.row,
1720
- rows: [rowObjs],
1721
- });
1722
- }
1723
- else {
1724
- let curRow = rowCells.find((x) => x.rowSpan == seqColSpanObj.row);
1725
- curRow.rows.push(rowObjs);
1726
- }
1727
- });
1728
- // 有值和没有值的行索引集合
1729
- let hasValueRows = [], noValueRows = [];
1730
- // 有值的行索引(序号列使用)
1731
- let hasValueRowsSer = [];
1732
- rowCells.forEach((rowObj, index) => {
1733
- if (rowObj.rows.some((x) => x.hasValue) && !hasValueRowsSer.some((x) => x == rowObj.rowSpan)) {
1734
- hasValueRowsSer.push(rowObj.rowSpan);
1735
- }
1736
- if (rowObj.rows.some((x) => x.hasValue)) {
1737
- rowObj.rows.forEach((x) => {
1738
- x.rows.forEach((rowIndex) => {
1739
- if (!hasValueRows.some((hItem) => hItem == rowIndex)) {
1740
- hasValueRows.push(rowIndex);
1741
- }
1742
- });
1743
- });
1744
- }
1745
- else {
1746
- rowObj.rows.forEach((x) => {
1747
- x.rows.forEach((rowIndex) => {
1748
- if (!noValueRows.some((hItem) => hItem == rowIndex)) {
1749
- noValueRows.push(rowIndex);
1750
- }
1751
- });
1752
- });
1753
- }
1754
- });
1755
- hasValueRowsSer.forEach((rowIndex, index) => {
1756
- // 设置序号列单元格的值(1、2、3...的格式)
1757
- sheet.setValue(rowIndex, 1, index + 1);
1758
- });
1759
- hasValueRows.forEach((rowIndex, index) => {
1760
- // 设置行可见
1761
- sheet.setRowVisible(rowIndex, true);
1762
- });
1763
- noValueRows.forEach((rowIndex) => {
1764
- // 设置行不可见
1765
- sheet.setRowVisible(rowIndex, false);
1766
- });
1767
- /** 创建空白行单元格 */
1768
- const createBlackRowCell = () => {
1769
- // 工作表总高度
1770
- const sheetTotalHeight = pageDir == 1 ? 1055 : 615;
1771
- // 之前已经创建的空白行索引
1772
- let createBlackRowIndex = -1;
1773
- // 获取所有可见行的总高度
1774
- let allRowHeight = 0;
1775
- for (let i = 0; i < sheet.getRowCount(); i++) {
1776
- const curRowVisible = sheet.getRowVisible(i);
1777
- const blankRowCell = sheet.getTag(i, 1);
1778
- if (curRowVisible && (blankRowCell == null || blankRowCell == undefined || blankRowCell != 'BlankCell')) {
1779
- allRowHeight += sheet.getRowHeight(i);
1780
- }
1781
- // 设置已创建的空白行索引
1782
- if (blankRowCell == 'BlankCell') {
1783
- createBlackRowIndex = i;
1784
- }
1785
- }
1786
- // 针对纵表情况,工作表总高度-表头和表尾总高度>=remainingHeight,空白行不显示;<remainingHeight,空白行显示
1787
- // 是否显示空白行
1788
- let isShowBlankRow = true;
1789
- if (pageDir == 1 && allRowHeight - headerRangeHeight - footerRangeHeight >= remainingHeight) {
1790
- isShowBlankRow = false;
1791
- }
1792
- if (!isShowBlankRow) {
1793
- // 设置行不可见
1794
- if (createBlackRowIndex != -1) {
1795
- sheet.setRowVisible(createBlackRowIndex, false);
1796
- }
1797
- return;
1798
- }
1799
- // 获取到最后一行动态加载区域的行索引
1800
- const lastRowIndex = dynamicLoadRangeJson[0].row + dynamicLoadRangeJson[0].rowCount - 1;
1801
- // 创建空白行
1802
- if (allRowHeight < sheetTotalHeight) {
1803
- // 获取空白行单元格的标签
1804
- const blankRowCell = sheet.getTag(lastRowIndex + 1, 1);
1805
- if (!blankRowCell || blankRowCell !== 'BlankCell') {
1806
- // 添加一行、合并单元格
1807
- sheet.addRows(lastRowIndex + 1, 1);
1808
- sheet.addSpan(lastRowIndex + 1, 1, 1, 77);
1809
- // 设置添加这一行的行高
1810
- sheet.setRowHeight(lastRowIndex + 1, sheetTotalHeight - allRowHeight);
1811
- // 获取添加这一行的区域范围
1812
- const addRowRange = sheet.getRange(lastRowIndex + 1, 1, 1, 77);
1813
- // 设置边框线
1814
- addRowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.thin), { all: true });
1815
- addRowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.medium), {
1816
- left: true,
1817
- right: true,
1818
- top: false,
1819
- bottom: false,
1820
- });
1821
- // 设置单元格水平和垂直居中
1822
- addRowRange.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
1823
- addRowRange.vAlign(GC.Spread.Sheets.HorizontalAlign.center);
1824
- sheet.setValue(lastRowIndex + 1, 1, blankRowCellValue);
1825
- sheet.setTag(lastRowIndex + 1, 1, 'BlankCell');
1826
- }
1827
- else {
1828
- // 设置添加这一行的行高
1829
- sheet.setRowHeight(lastRowIndex + 1, sheetTotalHeight - allRowHeight);
1830
- // 显示空白行单元格
1831
- sheet.setRowVisible(lastRowIndex + 1, true);
1832
- }
1833
- }
1834
- // 隐藏空白行单元格
1835
- else {
1836
- const blankRowCell = sheet.getTag(lastRowIndex + 1, 1);
1837
- // 如果空白行单元格标签存在,则隐藏
1838
- if (blankRowCell && blankRowCell == 'BlankCell') {
1839
- sheet.setRowVisible(lastRowIndex + 1, false);
1840
- }
1841
- }
1842
- };
1843
- createBlackRowCell();
1844
- // // 处理单元格边框线的问题
1845
- // const allRowIndex = orderByJson(unionJson(hasValueRows, noValueRows));
1846
- // const rowRange = sheet.getRange(allRowIndex[0], 1, allRowIndex.length, 77);
1847
- // rowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.thin), { all: true });
1848
- // rowRange.setBorder(new GC.Spread.Sheets.LineBorder('#000', GC.Spread.Sheets.LineStyle.medium), {
1849
- // left: true,
1850
- // right: true,
1851
- // top: false,
1852
- // bottom: false,
1853
- // });
1854
- // 恢复绘制
1855
- sheet.resumePaint();
1856
- return { hasValueIndex: hasValueRows, noValueIndex: noValueRows };
1857
- },
1858
1667
  };
1859
1668
 
1860
1669
  /**
@@ -23993,6 +23802,78 @@ const FormulaUtils = {
23993
23802
  return qdhsz;
23994
23803
  },
23995
23804
  },
23805
+ {
23806
+ funName: 'YJZBPD',
23807
+ funDesc: '报告上根据技术要求进行坐标判定',
23808
+ funDefaultVal: null,
23809
+ funParams: [
23810
+ {
23811
+ name: '四边形坐标,格式如 (0,0):(3,7):(15,8):(9.5,3.3)',
23812
+ repeatable: false,
23813
+ optional: false,
23814
+ },
23815
+ {
23816
+ name: '目标点x坐标',
23817
+ repeatable: false,
23818
+ optional: false,
23819
+ },
23820
+ {
23821
+ name: '目标点y坐标',
23822
+ repeatable: false,
23823
+ optional: false,
23824
+ },
23825
+ ],
23826
+ funCallback: (spread, sheet, retData) => {
23827
+ // 如果传递的参数小于3个,则返回/
23828
+ if (retData.allCellVals.length < 3) {
23829
+ return '/';
23830
+ }
23831
+ let points = retData.allCellVals[0], xPoint = retData.allCellVals[1], yPoint = retData.allCellVals[2];
23832
+ // 1. 格式校验
23833
+ if (typeof points !== 'string' || !points)
23834
+ return '/';
23835
+ const regex = /^\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)\s*:\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)\s*:\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)\s*:\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)\s*$/;
23836
+ const match = points.match(regex);
23837
+ if (!match)
23838
+ return '/';
23839
+ // 2. 解析坐标
23840
+ const coords = [];
23841
+ for (let i = 1; i < match.length; i += 2) {
23842
+ coords.push({ x: parseFloat(match[i]), y: parseFloat(match[i + 1]) });
23843
+ }
23844
+ const tx = Number(xPoint), ty = Number(yPoint);
23845
+ if (isNaN(tx) || isNaN(ty))
23846
+ return '/';
23847
+ // 3. 【新增】边界判定:点到线段距离 ≤ 容差 → 直接合格
23848
+ const EPSILON = 1e-9;
23849
+ function pointToSegmentDistSq(px, py, ax, ay, bx, by) {
23850
+ const dx = bx - ax, dy = by - ay;
23851
+ const lenSq = dx * dx + dy * dy;
23852
+ if (lenSq === 0)
23853
+ return (px - ax) ** 2 + (py - ay) ** 2; // 退化为点
23854
+ let t = ((px - ax) * dx + (py - ay) * dy) / lenSq;
23855
+ t = Math.max(0, Math.min(1, t)); // 钳制到 [0,1]
23856
+ const projX = ax + t * dx, projY = ay + t * dy;
23857
+ return (px - projX) ** 2 + (py - projY) ** 2;
23858
+ }
23859
+ const n = coords.length;
23860
+ for (let i = 0, j = n - 1; i < n; j = i++) {
23861
+ const distSq = pointToSegmentDistSq(tx, ty, coords[j].x, coords[j].y, coords[i].x, coords[i].y);
23862
+ if (distSq <= EPSILON * EPSILON)
23863
+ return '合格';
23864
+ }
23865
+ // 4. 射线法判定内部
23866
+ let inside = false;
23867
+ for (let i = 0, j = n - 1; i < n; j = i++) {
23868
+ const xi = coords[i].x, yi = coords[i].y;
23869
+ const xj = coords[j].x, yj = coords[j].y;
23870
+ const intersect = yi > ty !== yj > ty && tx < ((xj - xi) * (ty - yi)) / (yj - yi) + xi;
23871
+ if (intersect)
23872
+ inside = !inside;
23873
+ }
23874
+ return inside ? '合格' : '不合格';
23875
+ },
23876
+ },
23996
23877
  {
23997
23878
  funName: 'YJTEST',
23998
23879
  funDesc: '云检测试函数',