知识点:

1.导入导出

2.分页功能

3.增删改查

4.批量删除

5.批量编辑(审核)

6.列排序与列搜索

7.顶部搜索实现所有列搜索

8.高级搜索实现多条件搜索

9.顶部与刷新与视图列

10.实现文本类型明细行

11.列的统计

12.隐藏列,时间日期列格式化

13.新窗口打开

14.随机数据

15.自由编辑

16.清空数据

17.模板下载

截图

基础工程

表格组件导出 Excel Word Html Pdf

注入FreeSqlDataService服务,支持全数据导出

更新包

<PackageReference Include="BootstrapBlazor" Version="7.2.3-beta03" />
<PackageReference Include="Densen.FreeSql.Extensions.BootstrapBlazor" Version="7.*" />

Program.cs 添加代码

using Densen.DataAcces.FreeSql;
builder.Services.AddSingleton(typeof(FreeSqlDataService<>));
builder.Services.ConfigureJsonLocalizationOptions(op =>
{
// 忽略文化信息丢失日志
op.IgnoreLocalizerMissing = true;
});

Index.razor添加一个 TabItem

Tab 顺便改为懒加载

<Tab IsLazyLoadTabItem="true">
...
<TabItem Text="综合演示">
<ImpExpIII />
</TabItem>
</Tab>

添加打印预览 Pages\_Host.cshtml

< / body > 前加一句

    <script>
function printDiv() {
window.print();
}
</script>

数据实体类 Data\SalesChannels.cs

查看代码

```
using BootstrapBlazor.Components;
using DocumentFormat.OpenXml.Wordprocessing;
using FreeSql.DataAnnotations;
using Magicodes.ExporterAndImporter.Excel;
using OfficeOpenXml.Table;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace b14table.Data;

[ExcelImporter(IsLabelingError = true)]

[ExcelExporter(Name = "导入商品中间表", TableStyle = TableStyles.Light10, AutoFitAllColumn = true)]

[AutoGenerateClass(Searchable = true, Filterable = true, Sortable = true, ShowTips = true)]

public class SalesChannels

{

[AutoGenerateColumn(Ignore = true)]

[Column(IsIdentity = true)]

[DisplayName("序号")]

public int ID { get; set; }

[AutoGenerateColumn(ComponentType = typeof(ColorPicker), Width = 30)]
[DisplayName("级别")]
public string? Background { get; set; } [AutoGenerateColumn(FormatString = "yyyy-MM-dd")]
[DisplayName("日期")]
public DateTime Date { get; set; } [Required(ErrorMessage = "{0}不能为空")]
[DisplayName("名称")]
public string? Name { get; set; } [DisplayName("项目数量")]
public int Projects { get; set; } [DisplayName("交单数量")]
public int Orders { get; set; } [DisplayName("结单数量")]
public int Checkouts { get; set; } // 编辑界面无法显示小数, 以后再思考
[DisplayName("结单率")]
[AutoGenerateColumn(Readonly = true)]
public string? CheckoutRates { get => GetCheckoutRates(Checkouts, Orders); set => checkoutRates = value; }
string? checkoutRates; [DisplayName("合格数量")]
public int Qualifieds { get; set; } [DisplayName("合格率")]
[AutoGenerateColumn(Readonly = true)]
public string? QualifiedRates { get => GetQualifiedRates(Qualifieds, Checkouts); set => qualifiedRates = value; }
string? qualifiedRates; [DisplayName("总价值")]
public int Total { get; set; } [DisplayName("应收款")]
public int Receivables { get; set; } [DisplayName("已收款")]
public int Received { get; set; } [AutoGenerateColumn(FormatString = "HH:mm:ss")]
[DisplayName("修改日期")]
public DateTime ModifiedDate { get; set; } = DateTime.Now; [AutoGenerateColumn(TextEllipsis = true, Visible = false, ShowTips = true, ComponentType = typeof(Textarea))]
[DisplayName("备注")]
public string? Remark { get; set; } [AutoGenerateColumn(Visible = false, ComponentType = typeof(BootstrapInput<decimal>), Width = 80)]
[DisplayName("Test1")]
public decimal Test1 { get; set; } private string GetCheckoutRates(int checkouts, int orders) => orders > 0 ? (checkouts /(double) orders).ToString("P2") : "0%"; private string GetQualifiedRates(int qualifieds, int checkouts) => checkouts > 0 ? (qualifieds / (double)checkouts).ToString("P2") : "0%";

}

</details>

### 页面 `Pages\ImpExpIII.razor`

<details>
<summary>查看代码</summary>

@page "/impexpiii"

@using b14table.Data

@using static Blazor100.Service.ImportExportsService

综合演示

<SearchTemplate>
<GroupBox Title="搜索">
<div class="row g-3 form-inline">
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.Name" maxlength="50" ShowLabel="true" />
</div>
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.Date" maxlength="500" ShowLabel="true" />
</div>
</div>
</GroupBox>
</SearchTemplate> <DetailRowTemplate>
<div>备注: @context.Remark </div>
</DetailRowTemplate> <TableFooter Context="context1"> <TableFooterCell Text="当前页小计:" colspan="4" />
<TableFooterCell Text="总价值" colspan="3" />
<TableFooterCell Aggregate="@Aggregate" Field="@nameof(SalesChannels.Total)" /> <TableFooterCell Text="应收款" colspan="3" />
<TableFooterCell Aggregate="@Aggregate" Field="@nameof(SalesChannels.Receivables)" /> <TableFooterCell Text="已收款" colspan="3" />
<TableFooterCell Aggregate="@Aggregate" Field="@nameof(SalesChannels.Received)" /> </TableFooter> <TableToolbarTemplate>
<TableToolbarButton TItem="SalesChannels" Color="Color.Primary" Text="自由编辑" OnClick="@IsExcelToggle" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Warning" Text="随机数据" IsAsync OnClick="@GetDatasAsync" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Secondary" Text="导入" IsAsync OnClick="@ImportExcel" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Danger" Text="清空" IsAsync OnClick="EmptyAll" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Success" Text="模板" IsAsync OnClick="Export模板Async" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Success" Text="打印" IsAsync OnClickCallback="@PrintPreview" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Secondary" Text="新窗口打开" IsAsync OnClick="@新窗口打开" />
<TableToolbarButton TItem="SalesChannels" Color="Color.Secondary" Text="批量审批" IsAsync OnClickCallback="@批量审批" />
</TableToolbarTemplate> <ExportButtonDropdownTemplate>
<h6 class="dropdown-header">当前页数据</h6>
<div class="dropdown-item" @onclick="_=>ExportExcelAsync(list1.Rows)">
<i class="fas fa-file-excel"></i>
<span>Excel</span>
</div>
<div class="dropdown-item" @onclick="_=>ExportWordAsync(list1.Rows)">
<i class="fas fa-file-word"></i>
<span>Word</span>
</div>
<div class="dropdown-item" @onclick="_=>ExportHtmlAsync(list1.Rows)">
<i class="fa-brands fa-html5"></i>
<span>Html</span>
</div>
<div class="dropdown-item" @onclick="_=>ExportPDFAsync(list1.Rows)">
<i class="fas fa-file-pdf"></i>
<span>PDF</span>
</div>
<div class="dropdown-divider"></div>
<h6 class="dropdown-header">全部数据</h6>
<div class="dropdown-item" @onclick="_=>ExportExcelAsync(DataService.GetAllItems())">
<i class="fas fa-file-excel"></i>
<span>Excel</span>
</div>
<div class="dropdown-item" @onclick="_=>ExportWordAsync(DataService.GetAllItems())">
<i class="fas fa-file-word"></i>
<span>Word</span>
</div>
<div class="dropdown-item" @onclick="_=>ExportHtmlAsync(DataService.GetAllItems())">
<i class="fa-brands fa-html5"></i>
<span>Html</span>
</div>
<div class="dropdown-item" @onclick="_=>ExportPDFAsync(DataService.GetAllItems())">
<i class="fas fa-file-pdf"></i>
<span>PDF</span>
</div>
</ExportButtonDropdownTemplate>

```

页面代码 Pages\ImpExpIII.razor

查看代码

```
using AmeBlazor.Components;
using b14table.Data;
using Blazor100.Service;
using BootstrapBlazor.Components;
using Densen.DataAcces.FreeSql;
using DocumentFormat.OpenXml.Spreadsheet;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
using System.Diagnostics.CodeAnalysis;
using static Blazor100.Service.ImportExportsService;

namespace b14table.Pages

{

public partial class ImpExpIII

{

    [Inject]
IWebHostEnvironment? HostEnvironment { get; set; } [Inject]
[NotNull]
NavigationManager? NavigationManager { get; set; } [Inject]
[NotNull]
ImportExportsService? ImportExportsService { get; set; } [Inject]
[NotNull]
ToastService? ToastService { get; set; } [Inject]
[NotNull]
FreeSqlDataService<SalesChannels>? DataService { get; set; } [NotNull]
Table<SalesChannels>? list1 { get; set; } [Parameter] public int Footercolspan1 { get; set; } = 3; [Parameter] public int Footercolspan2 { get; set; } = 2; [Parameter] public int Footercolspan3 { get; set; } [Parameter] public int FootercolspanTotal { get; set; } = 2; [Parameter] public string? FooterText { get; set; } = "合计:"; [Parameter] public string? FooterText2 { get; set; } [Parameter] public string? FooterText3 { get; set; } [Parameter] public string? FooterTotal { get; set; } /// <summary>
/// 获得/设置 IJSRuntime 实例
/// </summary>
[Inject]
[NotNull]
protected IJSRuntime? JsRuntime { get; set; }
[Parameter] public string? 新窗口打开Url { get; set; } = "https://localhost:7292/"; // 由于使用了FreeSql ORM 数据服务,可以直接取对象
[Inject]
[NotNull]
IFreeSql? fsql { get; set; } [Inject] ToastService? toastService { get; set; }
[Inject] SwalService? SwalService { get; set; } public bool IsExcel { get; set; }
public bool DoubleClickToEdit { get; set; } = true;
protected string UploadPath = "";
protected string? uploadstatus;
long maxFileSize = 1024 * 1024 * 15;
string? tempfilename; private AggregateType Aggregate { get; set; } protected async Task GetDatasAsync()
{
var datas = GetDemoDatas();
await fsql.Insert<SalesChannels>().AppendData(datas).ExecuteAffrowsAsync();
await list1!.QueryAsync();
} protected override async void OnAfterRender(bool firstRender)
{
if (firstRender)
{
UploadPath = Path.Combine(HostEnvironment!.WebRootPath, "uploads");
if (!Directory.Exists(UploadPath)) Directory.CreateDirectory(UploadPath);
await list1!.QueryAsync();
}
} protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
//懒的人,直接初始化一些数据用用
var res = fsql.Select<SalesChannels>().Count();
if (res == 0)
{
var datas = GetDemoDatas();
await fsql.Insert<SalesChannels>().AppendData(datas).ExecuteAffrowsAsync();
await list1!.QueryAsync();
}
}
} public List<SalesChannels> GetDemoDatas()
{ var list = new List<SalesChannels>();
for (int i = 0; i < 100; i++)
{
try
{
var total = Random.Shared.Next(100, 3000);
list.Add(new SalesChannels()
{
ID = i,
Name = "渠道" + i,
Date = DateTime.Now,
Projects = Random.Shared.Next(10, 55),
Orders = Random.Shared.Next(3, 10),
Qualifieds = i,
Total = total,
Receivables = total - i,
Received = i,
Remark= $"{i} 明细行内嵌套另外一个 Table 组件,由于每行都要关联子表数据,出于性能的考虑,此功能采用 懒加载 模式,即点击展开按钮后,再对嵌套 Table 进行数据填充,通过 ShowDetailRow 回调委托可以控制每一行是否显示明细行,本例中通过 Complete 属性来控制是否显示明细行,可通过翻页来测试本功能"
}); }
catch (Exception e)
{
System.Console.WriteLine(e.Message);
}
}
return list; } private Task IsExcelToggle()
{
IsExcel = !IsExcel;
DoubleClickToEdit = !IsExcel;
StateHasChanged();
return Task.CompletedTask;
} public async Task<bool> Export模板Async()
{
await Export();
return true;
} private async Task<bool> ExportExcelAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Excel);
private async Task<bool> ExportPDFAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Pdf);
private async Task<bool> ExportWordAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Word);
private async Task<bool> ExportHtmlAsync(IEnumerable<SalesChannels> items) => await ExportAutoAsync(items, ExportType.Html); private async Task<bool> ExportAutoAsync(IEnumerable<SalesChannels> items, ExportType exportType = ExportType.Excel)
{
if (items == null || !items.Any())
{
await ToastService.Error("提示", "无数据可导出");
return false;
}
var option = new ToastOption()
{
Category = ToastCategory.Information,
Title = "提示",
Content = $"导出正在执行,请稍等片刻...",
IsAutoHide = false
};
// 弹出 Toast
await ToastService.Show(option);
await Task.Delay(100); // 开启后台进程进行数据处理
await Export(items?.ToList(), exportType); // 关闭 option 相关联的弹窗
option.Close(); // 弹窗告知下载完毕
await ToastService.Show(new ToastOption()
{
Category = ToastCategory.Success,
Title = "提示",
Content = $"导出成功,请检查数据",
IsAutoHide = false
});
return true; } private async Task Export(List<SalesChannels>? items = null, ExportType exportType = ExportType.Excel)
{
try
{
if (items == null || !items.Any())
{
ToastService?.Error($"导出", $"{exportType}出错,无数据可导出");
return;
}
var fileName = items == null ? "模板" : typeof(SalesChannels).Name;
var fullName = Path.Combine(UploadPath, fileName);
fullName = await ImportExportsService.Export(fullName, items, exportType);
fileName = (new System.IO.FileInfo(fullName)).Name;
ToastService?.Success("提示", fileName + "已生成"); //下载后清除文件
NavigationManager.NavigateTo($"uploads/{fileName}", true);
_ = Task.Run(() =>
{
Thread.Sleep(50000);
System.IO.File.Delete(fullName);
}); }
catch (Exception e)
{
ToastService?.Error($"导出", $"{exportType}出错,请检查. {e.Message}");
}
} public async Task<bool> EmptyAll()
{
fsql.Delete<SalesChannels>().Where(a => 1 == 1).ExecuteAffrows();
await ToastService!.Show(new ToastOption()
{
Category = ToastCategory.Success,
Title = "提示",
Content = "已清空数据",
}); await list1!.QueryAsync();
return true;
}
private async Task ImportExcel()
{
if (string.IsNullOrEmpty(tempfilename))
{
ToastService?.Error("提示", "请正确选择文件上传");
return;
}
var option = new ToastOption()
{
Category = ToastCategory.Information,
Title = "提示",
Content = "导入文件中,请稍等片刻...",
IsAutoHide = false
};
// 弹出 Toast
await ToastService!.Show(option);
await Task.Delay(100); // 开启后台进程进行数据处理
var isSuccess = await MockImportExcel(); // 关闭 option 相关联的弹窗
option.Close(); // 弹窗告知下载完毕
await ToastService.Show(new ToastOption()
{
Category = isSuccess ? ToastCategory.Success : ToastCategory.Error,
Title = "提示",
Content = isSuccess ? "操作成功,请检查数据" : "出现错误,请重试导入或者上传",
IsAutoHide = false
}); await list1!.QueryAsync();
}
private async Task<bool> MockImportExcel()
{
var items_temp = await ImportExportsService!.ImportFormExcel<SalesChannels>(tempfilename!);
if (items_temp.items == null)
{
ToastService?.Error("提示", "文件导入失败: " + items_temp.error);
return false;
}
//items = SmartCombine(items_temp, items).ToList(); 新数据和老数据合并处理,略100字
await fsql.Insert<SalesChannels>().AppendData(items_temp!.items.ToList()).ExecuteAffrowsAsync();
return true;
} protected async Task OnChange(InputFileChangeEventArgs e)
{
if (e.File == null) return;
tempfilename = Path.Combine(UploadPath, e.File.Name);
await using FileStream fs = new(tempfilename, FileMode.Create);
using var stream = e.File.OpenReadStream(maxFileSize);
await stream.CopyToAsync(fs); //正式工程此处是回调,简化版必须InvokeAsync一下,自由发挥
_ = Task.Run(async () => await InvokeAsync(async () => await ImportExcel())); } /// <summary>
/// 导出数据方法
/// </summary>
/// <param name="Items"></param>
/// <param name="opt"></param>
/// <returns></returns>
protected async Task<bool> ExportAsync(IEnumerable<SalesChannels> Items, QueryPageOptions opt)
{
var ret = await ExportExcelAsync(Items);
return ret;
} public Task PrintPreview(IEnumerable<SalesChannels> item)
{
//实际工程自己完善js打印
JsRuntime.InvokeVoidAsync("printDiv");
return Task.CompletedTask;
} private Task 新窗口打开()
{
if (string.IsNullOrEmpty(新窗口打开Url))
{
ToastService?.Error("提示", "Url为空!");
return Task.CompletedTask;
}
JsRuntime.NavigateToNewTab(新窗口打开Url);
return Task.CompletedTask;
} public async Task 批量审批(IEnumerable<SalesChannels> items)
{
items.ToList().ForEach(a =>
{
a.Checkouts = a.Orders;
a.Receivables = 0;
a.Received = a.Total;
a.ModifiedDate = DateTime.Now;
});
var res = await fsql.Update<SalesChannels>().SetSource(items).ExecuteAffrowsAsync(); await SwalService!.Show(new SwalOption()
{
Title = res == 0 ? "提示: 操作失败" : "提示: 操作成功" });
if (res != 0) await list1!.QueryAsync(); } }

}

</details>

### 预览

![输入图片说明](https://foruda.gitee.com/images/1673727731911583102/38d46153_125049.gif "QQ录屏2023011421sss1106 (1).gif")

### 源代码

https://github.com/densen2014/Blazor100/tree/master/b04table

https://gitee.com/densen2014/Blazor100/tree/master/b04table

[硬核] Bootstrap Blazor Table 综合演示例子的更多相关文章

  1. Bootstrap Blazor Table 组件(二)

    原文链接:https://www.cnblogs.com/ysmc/p/16128206.html 很多小伙伴在使用 Bootstrap Blazor Table组件的时候,都会有这样的一个需求: 我 ...

  2. Bootstrap Blazor Table 组件(四)自定义列生成

    原文链接:https://www.cnblogs.com/ysmc/p/16223154.html Bootstrap Blazor 官方链接:https://www.blazor.zone/tabl ...

  3. Bootstrap Blazor Table 组件(三)智能生成

    原文链接:https://www.cnblogs.com/ysmc/p/16201153.html Bootstrap Blazor 官网地址:https://www.blazor.zone 有了解过 ...

  4. Bootstrap Blazor 组件介绍 Table (一)自动生成列功能介绍

    Bootstrap Blazor 是一套企业级 UI 组件库,适配移动端支持各种主流浏览器,已经在多个交付项目中使用.通过本套组件可以大大缩短开发周期,节约开发成本.目前已经开发.封装了 70 多个组 ...

  5. Bootstrap Blazor 组件介绍 Table (二)自定义模板列功能介绍

    Bootstrap Blazor 是一套企业级 UI 组件库,适配移动端支持各种主流浏览器,已经在多个交付项目中使用.通过本套组件可以大大缩短开发周期,节约开发成本.目前已经开发.封装了 70 多个组 ...

  6. Bootstrap Blazor 组件介绍 Table (三)列数据格式功能介绍

    Bootstrap Blazor 是一套企业级 UI 组件库,适配移动端支持各种主流浏览器,已经在多个交付项目中使用.通过本套组件可以大大缩短开发周期,节约开发成本.目前已经开发.封装了 70 多个组 ...

  7. bootstrap table 服务器端分页例子分享

    这篇文章主要介绍了bootstrap table 服务器端分页例子分享,需要的朋友可以参考下 1,前台引入所需的js 可以从官网上下载 复制代码代码如下: function getTab(){var ...

  8. Bootstrap Blazor 开源UI库介绍-Table 虚拟滚动行

    今天我们来介绍一下 Bootstrap Blazor 中 Table 组件的虚拟滚动行,什么是虚拟滚动呢,我查到的解释是:只渲染可视区域的列表项,非可见区域的 完全不渲染,在滚动条滚动时动态更新列表项 ...

  9. 重磅硬核 | 一文聊透对象在 JVM 中的内存布局,以及内存对齐和压缩指针的原理及应用

    欢迎关注公众号:bin的技术小屋 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章<从内核角度看IO模型的演变>,在这篇文章中我们通过图解的方式以 ...

  10. [转]bootstrap的table插件动态加载表头

    原文地址:https://blog.csdn.net/abubu123/article/details/78060321 bootstrap的table属性已经很熟悉了,最近遇到一个问题,犹豫每个列表 ...

随机推荐

  1. LeetCode------两数之和(3)【数组】

    来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/two-sum 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 ...

  2. Java获取/resources目录下的资源文件方法

    Web项目开发中,经常会有一些静态资源,被放置在resources目录下,随项目打包在一起,代码中要使用的时候,通过文件读取的方式,加载并使用: 今天总结整理了九种方式获取resources目录下文件 ...

  3. Python基础部分:12、文件光标移动(补充)

    目录 一.文件内光标移动实际案例 二.计算机硬盘修改数据的原理 三.文件内容修改 一.文件内光标移动实际案例 # 1.二进制,只读模式,打a.txt文件 with open(r'a.txt', 'rb ...

  4. 2022春每日一题:Day 12

    题目:[SDOI2006]线性方程组 显然,高斯消元模板题 代码: #include <cstdio> #include <cstdlib> #include <cstr ...

  5. civil3d安装教程2022序列号和密钥

    Civil3D2021 WIN10 64位安装步骤:1.先使用"百度网盘客户端"下载C3D21_CN_x64软件安装包到电脑磁盘里,并右击进行解压,安装前先断网,然后找到Autod ...

  6. TortoiseGit间接处理linux目录下的仓库,用到window映射linux目录方案

    原始需求 习惯用TortoiseGit查看git仓库信息和历史日志,但这个工具只支持window,我希望linux也能用 虽然有其他linux的GUI的git工具,但我用到的linux基本都是无界面版 ...

  7. UBOOT编译--- UBOOT的顶层config.mk(五)

    1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概述 此文件包含在 ./Makefile 和 spl/Makefile 中. 清理状态以避免添加两次相同 ...

  8. Kafka事务原理剖析

    一.事务概览 提起事务,我们第一印象可能就是ACID,需要满足原子性.一致性.事务隔离级别等概念,那kafka的事务能做到什么程度呢?我们首先看一下如何使用事务 Producer端代码如下 Kafka ...

  9. Azure DevOps Server 用户组加入 Azure AD Domain Service 管理用户

    一,引言 今天我们继续讲解 Azure DevOps Server 的内容,对于管理用户组除了在 Azure DevOps Server 服务器上添加管理员方式外,还有没有其他方式,Azure Dev ...

  10. win7使用onedrive右键托盘图标中文不显示问题

    前言 win7 用的 onedrive不能在微软官网下载,用不了,所以需要下载 win7可以使用的版本. onedrive_for_win7.exe 解决问题 重启电脑解决 其他 我看贴吧说是文本放大 ...