VBA制作进销存全攻略,如何快速上手实现管理?
通过 VBA 制作进销存管理系统,只要明确业务流程、设计好数据结构并合理拆分「入库、出库、库存、报表」四大模块,就能在 Excel 中快速搭建一套可用的库存管理工具。整体思路是:先梳理商品、供应商、客户、单据等数据,再用 VBA 统一封装进销存逻辑,实现一键录单、自动更新库存、生成销售统计报表。相较纯手工表格,VBA 进销存管理在防错校验、自动计算、权限控制、日志追踪上更有优势,也更适合中小企业或个人商家做轻量级 ERP。对于不想从头开发的团队,则可以使用成熟的进销存模版工具,例如基于在线表单与流程的进销存系统,如「简道云进销存」一类的 SaaS,直接套用模板并按需扩展,也是高效可行的路线。
《VBA制作进销存全攻略,如何快速上手实现管理?》
VBA制作进销存全攻略,如何快速上手实现管理?
🧩 一、用 VBA 做进销存前,先搞清楚业务长什么样
在开始敲任何一行 VBA 代码之前,最重要的是理解进销存管理系统到底要解决什么问题、需要哪些核心数据与流程。多数失败的 VBA 进销存项目,不是技术不行,而是业务没梳理清楚。
1.1 进销存系统的核心目标
围绕 VBA 进销存的关键目标,可以归纳为三点:
- 库存准确:任何时间点都能快速知道每个商品的实时库存、可用库存、在途库存等;
- 流程可追踪:每一笔进货、销售、退货都有来源、有单号、有时间、有经手人;
- 数据可统计:能按商品、客户、供应商、时间等维度输出销售报表、采购报表、库存预警报表。
这些目标决定了 VBA 进销存系统的数据结构与模块划分。
1.2 典型进销存业务流程(适用于中小企业)
无论使用 VBA 还是专业 ERP,典型的进销存流程基本相似:
- 基础资料维护
- 商品档案(商品编码、名称、规格、单位、条码、分类等)
- 供应商档案(名称、联系方式、结算方式等)
- 客户档案(名称、等级、地区、联系人等)
- 仓库档案(仓库编码、仓库名称、地址等)
- 采购与入库流程
- 采购订单(向供应商下单)
- 采购入库(根据采购订单入库,生成入库单,更新库存)
- 采购退货(退给供应商,减少库存)
- 销售与出库流程
- 销售订单(客户下单)
- 销售出库(根据销售订单发货,生成出库单,扣减库存)
- 销售退货(客户退货,库存增加)
- 库存管理
- 实时库存查询(按商品、仓库查看数量)
- 库存盘点(期末盘点数量与系统数量差异调整)
- 库存调拨(仓库之间的库存转移)
- 报表分析
- 销售统计(按商品、客户、时间维度)
- 采购统计(按商品、供应商、时间维度)
- 库存预警(低库存预警、滞销品分析)
在 VBA 进销存中,这些流程会被分解到不同的 Sheet 与模块中,例如「基础资料」「入库单」「出库单」「库存表」「报表」等。
1.3 用 VBA 做进销存适合哪些场景?
VBA 进销存系统并不适合所有企业,理解其适用场景非常重要:
| 场景 | 用 VBA 进销存的适用程度 | 说明 |
|---|---|---|
| 个人卖家/微商 | 高 | 商品数不多、业务简单,用 Excel + VBA 足够 |
| 小微企业/门店 | 中高 | 日订单量不大(几十到数百),多人操作要注意共享与权限 |
| 多门店连锁、复杂仓储 | 低 | 需要复杂的多仓协同、权限、移动端操作,VBA 维护成本高 |
| 电商多平台(跨境、多店) | 低 | 需要跨平台同步、API 对接,建议用专业 SaaS 系统 |
| 有严格审计/合规要求 | 中 | 可用 VBA+版本控制,或使用更专业的进销存系统配合审计需求 |
对于后两种复杂场景,更合适的是使用成熟的云端进销存系统或低代码平台。比如当你需要多角色协作、手机端录单、与财务系统对接时,可以考虑借助在线进销存模版工具,例如基于云端表单和流程引擎的「简道云进销存」这类方案,用可视化方式替代大量 VBA 自写逻辑,维护成本更可控。
📁 二、VBA 进销存系统的整体架构设计
在决定用 VBA 来实现进销存管理后,首要任务是规划整体架构和工作簿结构。这一步相当于画出 Excel 版「系统蓝图」。
2.1 VBA 进销存的工作簿结构划分
推荐采用「多 Sheet + 模块化 VBA」的结构,以便拆分职责,便于日后维护和扩展:
| 类型 | 建议 Sheet 名 | 主要用途 |
|---|---|---|
| 基础资料 | 商品档案、客户档案、供应商档案、仓库档案 | 存放所有主数据 |
| 单据录入 | 采购入库、销售出库、采购退货、销售退货 | 录入业务单据,触发库存变动逻辑 |
| 结果表/台账 | 库存台账、库存汇总 | 记录每次变动、汇总当前库存 |
| 报表 | 销售统计、采购统计、库存预警 | 用 VBA 统一生成报表,避免手工透视表 |
| 设置/参数 | 系统参数、代码表 | 存放下拉选项、单号前缀、税率、默认仓库等 |
| 隐藏日志(可选) | 操作日志 | 记录用户操作,便于审计与追踪 |
VBA 模块层面,可以按功能拆分:
modInit:初始化模块(创建表、设置格式、预填公式)modInventory:库存业务逻辑(加减库存、校验库存)modOrders:采购/销售单据处理(生成单号、写入台账)modReports:各类进销存报表生成逻辑modUtils:工具函数(日期处理、查找函数扩展、日志记录等)frm*:用户窗体模块(如frmPurchase,frmSale等)
2.2 数据表结构设计原则
Excel + VBA 的进销存系统,本质上是一个轻量级的关系型数据库。设计表结构时,可以参考 MySQL/SQL 的方式:
- 每张表一个主题
- 商品档案只放商品相关字段;
- 单据表只放单据信息,不要混入客户详细信息(用 ID 关联)。
- 使用编码而不是名称做关联
- 商品编码(ProductID)
- 客户编码(CustomerID)
- 供应商编码(SupplierID)
- 仓库编码(WarehouseID)
- 字段命名清晰、统一
- 用英文+下划线或者驼峰,如
OrderNo,ProductCode,Qty,UnitPrice; - 避免中文列名参与 VBA 计算,减少编码与兼容性问题。
2.3 关键数据表字段示例
以下是 VBA 进销存中常用表的字段设计示例(可根据实际需求调整):
2.3.1 商品档案表(Sheet:商品档案)
| 字段名 | 类型/示例 | 说明 |
|---|---|---|
| ProductID | 文本:P0001 | 商品编码(唯一) |
| ProductName | 文本:苹果 | 商品名称 |
| Spec | 文本:500g/袋 | 规格型号 |
| Unit | 文本:袋 | 计量单位 |
| Category | 文本:水果 | 商品分类 |
| Barcode | 文本/数字 | 条形码,可用于扫码输入 |
| SafetyStockQty | 数字:100 | 安全库存量,用于库存预警 |
| IsActive | 是/否 | 是否启用 |
2.3.2 客户档案(Sheet:客户档案)
| 字段名 | 类型/示例 | 说明 |
|---|---|---|
| CustomerID | 文本:C0001 | 客户编码(唯一) |
| CustomerName | 文本:某某超市 | 客户名称 |
| Contact | 文本:张三 | 联系人 |
| Phone | 文本 | 电话 |
| Region | 文本:上海/浦东 | 地区 |
| Level | 文本:A级/B级等 | 客户等级 |
2.3.3 采购入库单(Sheet:采购入库)
以「一行一明细」方式记录:
| 字段名 | 示例 | 说明 |
|---|---|---|
| InboundNo | PI202501010001 | 采购入库单号 |
| InboundDate | 2025-01-01 | 入库日期 |
| SupplierID | S0001 | 供应商编码 |
| WarehouseID | W0001 | 仓库编码 |
| ProductID | P0001 | 商品编码 |
| Qty | 100 | 入库数量 |
| UnitPrice | 5.5 | 含税单价 |
| Amount | 550 | 金额(Qty*UnitPrice) |
| Operator | 用户名 | 操作员 |
| Remark | 文本 | 备注 |
2.3.4 销售出库单(Sheet:销售出库)
字段类似,只是供应商改为客户,并由库存减少:
| 字段名 | 示例 | 说明 |
|---|---|---|
| OutboundNo | SO202501010001 | 销售出库单号 |
| OutboundDate | 2025-01-01 | 出库日期 |
| CustomerID | C0001 | 客户编码 |
| WarehouseID | W0001 | 仓库编码 |
| ProductID | P0001 | 商品编码 |
| Qty | 50 | 出库数量 |
| UnitPrice | 8.0 | 销售单价 |
| Amount | 400 | 金额 |
| Operator | 用户名 | 操作员 |
2.3.5 库存台账表(Sheet:库存台账)
库存台账记录每一次库存变动,是 VBA 进销存系统的「事实表」:
| 字段名 | 示例 | 说明 |
|---|---|---|
| TransID | 自增 ID | 记录 ID |
| TransDate | 2025-01-01 | 业务日期 |
| TransType | IN / OUT / ADJ | 入库、出库、调整 |
| RefNo | PI2025…/SO2025… | 关联单号 |
| ProductID | P0001 | 商品编码 |
| WarehouseID | W0001 | 仓库编码 |
| QtyChange | +100 / -50 | 库存变动数量 |
| BalanceQty | 期末结余数量 | 可选,用于加速查询 |
通过这张「库存台账」,VBA 可以按商品+仓库汇总得到当前库存,避免在多张表中来回查找。
🧮 三、Excel 基础搭建:为 VBA 进销存打地基
在使用 VBA 制作进销存管理之前,需要把 Excel 的基础结构搭起来。这部分更偏「表格设计」,但决定了后续 VBA 代码是否好写、好维护。
3.1 准备基础工作簿与 Sheet
步骤建议如下:
- 新建一个工作簿:命名为
InventorySystem.xlsm(必须是启用宏的格式) - 按上文设计创建以下 Sheet:
商品档案客户档案供应商档案仓库档案采购入库销售出库库存台账库存汇总销售统计系统参数
- 在
系统参数中设置:
- 单号前缀(如采购 PI、销售 SO)
- 默认仓库编码
- 税率(如 13%)
- 版本号等
3.2 设计输入表与下拉选择(数据验证)
为了让 VBA 进销存更加稳定,尽量让用户通过下拉框选择商品、客户,而不是手工输入。
示例:在 采购入库 Sheet 中设置数据验证:
- 使用命名区域
- 在
商品档案中,将 ProductID 列定义为名称:ProductList - 在
供应商档案中,将 SupplierID 列定义为:SupplierList
- 在
采购入库的商品编码列设置数据验证:
- 数据验证类型:序列
- 来源:
=ProductList
- 同理,供应商列设置为
=SupplierList。
这样在 VBA 进销存中,数据精确性会更高,也便于库存统计。
3.3 使用表格(ListObject)提高 VBA 可读性
建议将每个数据区域转换为 Excel 表格(快捷键 Ctrl+T),并命名:
tblProducts:商品档案tblSuppliers:供应商档案tblCustomers:客户档案tblInbound:采购入库tblOutbound:销售出库tblInvLedger:库存台账
在 VBA 中通过 ListObject 操作表格比直接用 Cells 更安全、可读性更高。
🧠 四、核心逻辑:用 VBA 实现进销存加减与校验
VBA 进销存的「心脏」,就是库存的加减与校验逻辑。所有「采购入库、销售出库、退货、盘点」操作,最终都会落到库存变动。
4.1 库存更新的基本思路
当录入一条单据时(比如采购入库):
- 校验单据完整性(是否选择商品、数量是否大于 0 等)
- 将单据明细写入对应的单据表,如
tblInbound - 在
库存台账中增加一条记录:
TransType = INQtyChange = +数量
- 更新库存汇总(可选:实时更新,或在查询时动态计算)
销售出库则类似:
TransType = OUTQtyChange = -数量- 先校验当前库存是否足够;
- 不足则提示「库存不足」,禁止提交。
4.2 用 VBA 封装库存调整函数
可以在 modInventory 中编写一个通用函数 UpdateInventory:
Public Function UpdateInventory(ByVal TransDate As Date, _ByVal TransType As String, _ByVal RefNo As String, _ByVal ProductID As String, _ByVal WarehouseID As String, _ByVal Qty As Double) As BooleanDim wsLedger As WorksheetDim lo As ListObjectDim newRow As ListRowDim QtyChange As Double
On Error GoTo ErrHandler
Set wsLedger = ThisWorkbook.Worksheets("库存台账")Set lo = wsLedger.ListObjects("tblInvLedger")
' 入库为正数,出库为负数Select Case UCase(TransType)Case "IN": QtyChange = QtyCase "OUT": QtyChange = -QtyCase "ADJ": QtyChange = Qty ' 调整可正可负Case ElseMsgBox "无效库存变动类型:" & TransType, vbExclamationUpdateInventory = FalseExit FunctionEnd Select
' 库存校验:出库时检查是否足够If QtyChange < 0 ThenIf Not CheckStockEnough(ProductID, WarehouseID, -QtyChange) ThenMsgBox "库存不足,无法出库。", vbCriticalUpdateInventory = FalseExit FunctionEnd IfEnd If
' 在库存台账中新增一行Set newRow = lo.ListRows.AddWith newRow.Range.Columns(lo.ListColumns("TransDate").Index).Value = TransDate.Columns(lo.ListColumns("TransType").Index).Value = TransType.Columns(lo.ListColumns("RefNo").Index).Value = RefNo.Columns(lo.ListColumns("ProductID").Index).Value = ProductID.Columns(lo.ListColumns("WarehouseID").Index).Value = WarehouseID.Columns(lo.ListColumns("QtyChange").Index).Value = QtyChange' BalanceQty 可以在报表中计算,也可以此处计算End With
UpdateInventory = TrueExit Function
ErrHandler:MsgBox "更新库存失败:" & Err.Description, vbCriticalUpdateInventory = FalseEnd Function这里的 CheckStockEnough 是辅助函数,用来检查当前库存。
4.3 计算当前库存的 VBA 函数
在 VBA 进销存系统中,经常需要根据 ProductID + WarehouseID 查询当前库存。可以写一个函数:
Public Function GetCurrentStock(ByVal ProductID As String, _ByVal WarehouseID As String) As DoubleDim wsLedger As WorksheetDim lo As ListObjectDim rngProduct As Range, rngWarehouse As Range, rngQty As RangeDim i As Long
Set wsLedger = ThisWorkbook.Worksheets("库存台账")Set lo = wsLedger.ListObjects("tblInvLedger")
With lo.DataBodyRangeFor i = 1 To .Rows.CountIf .Cells(i, lo.ListColumns("ProductID").Index).Value = ProductID _And .Cells(i, lo.ListColumns("WarehouseID").Index).Value = WarehouseID Then
GetCurrentStock = GetCurrentStock + _.Cells(i, lo.ListColumns("QtyChange").Index).ValueEnd IfNext iEnd WithEnd Function在 CheckStockEnough 中调用:
Public Function CheckStockEnough(ByVal ProductID As String, _ByVal WarehouseID As String, _ByVal NeedQty As Double) As BooleanDim currentQty As DoublecurrentQty = GetCurrentStock(ProductID, WarehouseID)CheckStockEnough = (currentQty >= NeedQty)End Function由于 VBA 循环可能较慢,如果进销存数据量大,可改用 Application.WorksheetFunction.SumIfs 或将库存汇总结果维护在 库存汇总 表中,提高性能。
4.4 单据保存:从表单到库存的完整流程
以采购入库为例,VBA 进销存的典型执行步骤:
- 用户在
采购入库Sheet 或窗体中录入:
- 入库日期
- 供应商
- 仓库
- 多行商品明细(商品、数量、单价)
- 点击「保存/提交」按钮
- VBA 执行以下逻辑:
- 检查是否填写完整、有无重复商品等
- 自动生成采购入库单号(后文详述)
- 将明细写入
采购入库表 - 对每一行商品调用
UpdateInventory(类型 IN) - 写入日志(可选)
在销售出库中,只是 TransType 换为 OUT,并增加库存校验逻辑。通过这种封装,VBA 进销存管理对业务逻辑的控制就比较严谨,不易出错。
🧾 五、单号生成与自动化录单界面设计
进销存管理要可追溯,一个规范的「单号规则」非常关键。VBA 可以很容易帮你在 Excel 中自动生成不重复的进销存单据编号。
5.1 规范的进销存单号设计
推荐单号结构:前缀 + 日期 + 流水号
例如:
- 采购入库:
PI202501010001 - 销售出库:
SO202501010001
其中:
- 前缀:表示单据类型(PI - Purchase Inbound;SO - Sales Outbound)
- 日期:
YYYYMMDD,当日维度 - 流水号:当日从 0001 开始递增
单号不仅是 VBA 进销存系统中的「主键」,还是报表统计、对账核查的关键字段。
5.2 VBA 自动生成单号示例
在 modUtils 中编写函数:
Public Function GenerateDocNo(ByVal DocType As String) As StringDim ws As WorksheetDim lastNo As StringDim todayStr As StringDim prefix As StringDim newSeq As Long
todayStr = Format(Date, "yyyymmdd")
Select Case UCase(DocType)Case "PI": prefix = "PI"Case "SO": prefix = "SO"Case "PR": prefix = "PR" ' 采购退货Case "SR": prefix = "SR" ' 销售退货Case Elseprefix = "UN"End Select
' 在系统参数中保存最后单号Set ws = ThisWorkbook.Worksheets("系统参数")
' 假设 A 列存 DocType, B 列存 LastNoDim rng As Range, found As RangeSet rng = ws.Range("A:A").Find(What:=DocType, LookIn:=xlValues, LookAt:=xlWhole)
If Not rng Is Nothing ThenlastNo = rng.Offset(0, 1).ValueElse' 新增一行Set rng = ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1, 0)rng.Value = DocTypelastNo = ""End If
If Left(lastNo, Len(prefix) + 8) = prefix & todayStr ThennewSeq = CLng(Right(lastNo, 4)) + 1ElsenewSeq = 1End If
GenerateDocNo = prefix & todayStr & Format(newSeq, "0000")
' 回写最新单号rng.Offset(0, 1).Value = GenerateDocNoEnd Function在采购入库保存时调用:docNo = GenerateDocNo("PI")。
5.3 使用 VBA 用户窗体优化录单体验
Excel 自带工作表虽然可以录入进销存数据,但对于大量单据,会显得拥挤、不易控制。利用 VBA 的 UserForm 可以创建「类似软件界面」的录单窗口:
- 顶部:单据头部信息
- 日期
- 供应商/客户
- 仓库
- 中部:明细列表(ListBox 或 FlexGrid)
- 商品、数量、单价、金额
- 底部:合计金额、税额、折扣等
5.3.1 表单设计关键点
- 使用下拉框 ComboBox 绑定商品列表、客户列表:
- 将
tblProducts作为数据源; - 录单时选择商品编码或商品名称。
- 支持扫码枪输入条码:
- 在条码文本框
txtBarcode_Change中,实时用 VBA 查找商品,并填充对应字段。
- 自动计算金额与合计:
- 在数量或单价变更时,自动计算金额;
- 汇总所有明细行得出合计金额,方便进行销售分析。
- 点击「保存」按钮时:
- 统一校验必填项
- 调用
GenerateDocNo - 循环写入 Excel 表
- 调用
UpdateInventory
通过这种方式,VBA 进销存系统就从「普通表格」升级成「半专业软件」的使用体验。
📊 六、库存台账、库存汇总与库存预警的实现
库存管理是 VBA 进销存系统的核心场景之一,重点在于三件事:准确记录、快速汇总、及时预警。
6.1 库存台账 vs 库存汇总:双表模式
为了兼顾详细记录与查询性能,推荐:
库存台账(tblInvLedger)保存所有变动记录;库存汇总表保存每个商品+仓库的当前库存。
| 表名称 | 数据粒度 | 典型用途 |
|---|---|---|
| 库存台账 | 每一笔变动一行 | 审计追溯、明细查询 |
| 库存汇总 | 每个商品+仓库一行 | 实时库存查询、出库校验 |
6.2 使用 VBA 维护库存汇总表
在 UpdateInventory 成功后,可以同步更新 库存汇总 表:
Private Sub UpdateInventorySummary(ByVal ProductID As String, _ByVal WarehouseID As String, _ByVal QtyChange As Double)Dim ws As WorksheetDim lo As ListObjectDim foundRow As ListRowDim i As Long
Set ws = ThisWorkbook.Worksheets("库存汇总")Set lo = ws.ListObjects("tblInvSummary")
' 查找是否已有该商品+仓库组合For i = 1 To lo.ListRows.CountWith lo.ListRows(i).RangeIf .Cells(1, lo.ListColumns("ProductID").Index).Value = ProductID _And .Cells(1, lo.ListColumns("WarehouseID").Index).Value = WarehouseID Then
.Cells(1, lo.ListColumns("CurrentQty").Index).Value = _.Cells(1, lo.ListColumns("CurrentQty").Index).Value + QtyChange
Exit SubEnd IfEnd WithNext i
' 如不存在则新增一行Dim newRow As ListRowSet newRow = lo.ListRows.AddWith newRow.Range.Cells(1, lo.ListColumns("ProductID").Index).Value = ProductID.Cells(1, lo.ListColumns("WarehouseID").Index).Value = WarehouseID.Cells(1, lo.ListColumns("CurrentQty").Index).Value = QtyChangeEnd WithEnd Sub在 UpdateInventory 函数末尾调用 UpdateInventorySummary 即可,使库存汇总与台账保持一致。
6.3 库存预警:安全库存 + VBA 条件判断
在商品档案中设置 SafetyStockQty 安全库存字段后,可以利用 库存汇总 表与商品档案做对比:
- 在
库存预警Sheet 中设计如下字段:
- ProductID
- ProductName
- WarehouseID
- CurrentQty
- SafetyStockQty
- IsLow(是否低于安全库存)
- 编写 VBA 例程
GenerateStockAlert:
Public Sub GenerateStockAlert()Dim wsAlert As WorksheetDim wsSummary As WorksheetDim wsProd As WorksheetDim loSummary As ListObjectDim loProd As ListObjectDim loAlert As ListObjectDim i As LongDim prodID As String, whID As StringDim currentQty As Double, safetyQty As Double
Set wsAlert = ThisWorkbook.Worksheets("库存预警")Set wsSummary = ThisWorkbook.Worksheets("库存汇总")Set wsProd = ThisWorkbook.Worksheets("商品档案")
Set loSummary = wsSummary.ListObjects("tblInvSummary")Set loProd = wsProd.ListObjects("tblProducts")Set loAlert = wsAlert.ListObjects("tblStockAlert")
' 清空旧数据On Error Resume NextDo While loAlert.ListRows.Count > 0loAlert.ListRows(1).DeleteLoopOn Error GoTo 0
' 遍历库存汇总For i = 1 To loSummary.ListRows.CountWith loSummary.ListRows(i).RangeprodID = .Cells(1, loSummary.ListColumns("ProductID").Index).ValuewhID = .Cells(1, loSummary.ListColumns("WarehouseID").Index).ValuecurrentQty = .Cells(1, loSummary.ListColumns("CurrentQty").Index).ValueEnd With
' 查找商品安全库存safetyQty = GetSafetyStockQty(prodID, loProd)
If currentQty < safetyQty Then' 新增预警行Dim newRow As ListRowSet newRow = loAlert.ListRows.AddWith newRow.Range.Cells(1, loAlert.ListColumns("ProductID").Index).Value = prodID.Cells(1, loAlert.ListColumns("WarehouseID").Index).Value = whID.Cells(1, loAlert.ListColumns("CurrentQty").Index).Value = currentQty.Cells(1, loAlert.ListColumns("SafetyStockQty").Index).Value = safetyQty.Cells(1, loAlert.ListColumns("IsLow").Index).Value = "是"End WithEnd IfNext iEnd Sub配合条件格式,例如 IsLow = 是 时整行背景变红,即可实现一个较清晰的库存预警界面,这也是 VBA 进销存系统中的常用功能。
📈 七、销售报表与采购报表的 VBA 自动统计
进销存系统的另一个重要价值,是通过报表实现管理决策支持。利用 VBA 可以实现自动生成销售报表、采购报表,而无需每次手工拖动数据透视表。
7.1 销售报表的常见需求
在 VBA 进销存中,常见的销售统计数据包括:
- 按商品统计销售数量与销售额;
- 按客户统计销售额、毛利;
- 按时间(天、周、月)统计销售趋势;
- 按业务员统计业绩。
这些报表可以基于 销售出库 表构建。
7.2 使用 VBA 汇总销售数据(按商品)
假设 销售出库 表 tblOutbound 包含字段:OutboundDate, ProductID, Qty, Amount。
可在 销售统计 Sheet 中通过 VBA 生成「商品维度」报表:
Public Sub GenerateSalesByProduct(ByVal StartDate As Date, ByVal EndDate As Date)Dim wsOut As Worksheet, wsRpt As WorksheetDim loOut As ListObject, loRpt As ListObjectDim dict As ObjectDim i As LongDim key As StringDim dDate As Date, prodID As StringDim qty As Double, amt As Double
Set wsOut = ThisWorkbook.Worksheets("销售出库")Set wsRpt = ThisWorkbook.Worksheets("销售统计")
Set loOut = wsOut.ListObjects("tblOutbound")Set loRpt = wsRpt.ListObjects("tblSalesByProduct")
' 清空旧数据On Error Resume NextDo While loRpt.ListRows.Count > 0loRpt.ListRows(1).DeleteLoopOn Error GoTo 0
Set dict = CreateObject("Scripting.Dictionary")
' 汇总数据For i = 1 To loOut.ListRows.CountWith loOut.ListRows(i).RangedDate = .Cells(1, loOut.ListColumns("OutboundDate").Index).ValueIf dDate >= StartDate And dDate <= EndDate ThenprodID = .Cells(1, loOut.ListColumns("ProductID").Index).Valueqty = .Cells(1, loOut.ListColumns("Qty").Index).Valueamt = .Cells(1, loOut.ListColumns("Amount").Index).Value
key = prodIDIf Not dict.Exists(key) Thendict.Add key, Array(0#, 0#) ' Qty, AmountEnd If
Dim arrarr = dict(key)arr(0) = arr(0) + qtyarr(1) = arr(1) + amtdict(key) = arrEnd IfEnd WithNext i
' 把结果写入报表表格Dim k As VariantFor Each k In dict.KeysDim newRow As ListRowDim arr2arr2 = dict(k)
Set newRow = loRpt.ListRows.AddWith newRow.Range.Cells(1, loRpt.ListColumns("ProductID").Index).Value = k.Cells(1, loRpt.ListColumns("TotalQty").Index).Value = arr2(0).Cells(1, loRpt.ListColumns("TotalAmount").Index).Value = arr2(1)End WithNext kEnd Sub在 销售统计 Sheet 上可以加两个日期输入框+按钮,点击后执行 GenerateSalesByProduct,即可生成指定期间内的销售报表。这是 VBA 进销存系统处理销售分析的基础。
7.3 采购报表逻辑类似
采购统计报表的逻辑与销售报表类似,只不过数据源换成 tblInbound,维度可能是「供应商」或「商品」。
制作采购报表可以帮助企业分析:
- 哪些供应商供货多、金额大;
- 哪些商品采购频率高,是否需要调整合同或采购计划;
- 采购价格趋势(可选)。
这些报表在实践中对于库存周转与采购计划制定非常重要。
7.4 使用图表与仪表盘增强管理视图
在 VBA 进销存系统中,可以进一步使用 Excel 图表构建「销售仪表盘」:
- 销售趋势折线图
- 商品销售排行榜条形图
- 库存周转率图表
- 低库存商品 TOP N
VBA 可以在更新报表时同步刷新这些图表,实现一键刷新「进销存数据看板」。
🔐 八、权限控制、数据保护与版本备份
相对于专业 ERP,基于 VBA 的进销存系统在权限与安全方面比较弱,但仍可做一些基本控制。
8.1 使用工作表保护与隐藏公式
可以针对不同 Sheet 设置保护:
- 允许用户编辑单据录入区域;
- 锁定公式列、汇总列;
- 隐藏敏感表(如
系统参数、库存台账); - 使用密码保护工作簿结构,避免随意添加或删除 Sheet。
虽然 Excel 密码保护并非不可破解,但在日常内部使用中足以防止误操作。
8.2 简单的用户角色控制(VBA 模拟)
如果 VBA 进销存系统有多个使用者,可以定义简单角色:
- 管理员:可查看所有表、修改基础资料;
- 录单员:只能录入采购/销售单据;
- 查询员:只能查看报表、不允许修改数据。
实现方式:
- 在
系统参数中维护用户表(用户名、角色、密码); - 在打开工作簿时弹出登录窗体;
- 登录成功后,根据角色:
- 隐藏/显示特定 Sheet;
- 禁用特定按钮(如设置按钮)。
虽然不能与专业权限系统相比,但对于中小团队的 VBA 进销存足以起到「软约束」作用。
8.3 版本备份与日志追踪
为了降低进销存数据的风险,建议:
- 定期备份整个工作簿(例如每天自动复制一份到备份文件夹);
- 在
操作日志Sheet 中记录重要操作:
- 操作时间、用户、操作类型、单号等;
- 使用 VBA 执行关键操作前写入日志。
通过这些方式,VBA 进销存系统可以具备基本的可追溯性,方便事后分析问题。
🧪 九、VBA 进销存系统的性能优化与常见坑
随着进销存数据量的增长(尤其是库存台账与销售记录),VBA 的性能问题会逐渐显现。合理的优化能延长系统可用寿命。
9.1 性能优化建议
- 减少逐行循环,使用数组批量读写
- 尽量避免在上万行数据上逐行
Cells(i, j)访问; - 使用
Variant数组一次性把数据读到内存,处理后再写回。
- 关闭屏幕刷新和自动计算
- 在长时间运行的 VBA 进销存脚本中:
Application.ScreenUpdating = False Application.Calculation = xlCalculationManual ’ …代码… Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = True
3. **合理使用筛选与 `SumIfs`**- 对简单汇总场景,可以调用 `WorksheetFunction.SumIfs`,而不是纯 VBA 循环。
4. **避免频繁选择与激活**- 不要使用 `.Select` 和 `Selection`;- 使用对象直接操作,如 `ws.Cells(row, col).Value`。
### 9.2 常见错误与规避方法
1. **未考虑多人同时编辑**- Excel/VBA 不擅长多人同时操作同一文件;- 如确有多人协作需求,可以使用共享工作簿或将数据放在共享网络盘,但容易出现冲突;- 对于多人协同的进销存场景,更推荐使用云端进销存工具,例如以在线表单和流程引擎为基础的系统,如「简道云进销存」这类,可以多人同时填写订单和处理库存动作。
2. **忽略数据验证,导致库存错乱**- 必须对关键字段做数据验证和 VBA 校验;- 不要允许匿名修改库存台账和库存汇总。
3. **单表过大,导致运行缓慢**- 当销售出库记录达到数十万行时,建议拆分按年份或按月归档;- 或将历史数据导出到外部数据库(如 Access、SQL Server)。
4. **硬编码列号、无注释**- 随着进销存系统演进,列结构可能调整;- 建议使用 ListObject 的列名访问,代码更稳定;- 适度注释,提高可维护性。
---
## 🧭 十、何时考虑从 VBA 进销存升级到云端系统?
用 VBA 制作进销存系统可以快速上手、成本低,但并不是适合所有阶段。理解其边界,有助于做长期规划。
### 10.1 VBA 进销存的优势与局限对比
| 维度 | VBA 进销存 | 云端/专业进销存系统 ||--------------|-----------------------------------------------|----------------------------------------------|| 成本 | 开发成本低,无需额外许可费用 | 一般按用户数/用量计费 || 上手速度 | 对熟悉 Excel 的人较快 | 初次配置需要时间 || 灵活性 | 高度可定制,代码可随时修改 | 部分场景需按产品既有逻辑 || 多人协作 | 弱,易冲突 | 支持多终端、多用户并发 || 数据安全 | 依赖本地备份,易受硬件故障影响 | 专业数据备份与权限体系 || 延展能力 | 难以对接其它系统(电商平台、财务、CRM 等) | 通常支持 API、插件或与其他 SaaS 集成 || 移动端使用 | 不便(需要 PC,或者复杂的 Office 方案) | 可用手机、平板等移动设备 || 复杂业务支持 | 难以维护复杂流程(多仓、多币种、批次、序列号)| 通常内置支持或可配置 |
当你在以下情况下,就应评估从 VBA 进销存升级:
- 需要多人同时录单、审核、查询库存;- 有多仓、多门店、多平台业务;- 需要扫码、移动端录单或现场盘点;- 需要与财务、物流、CRM 等系统打通。
### 10.2 使用低代码/云端模版作为过渡方案
如果你已经有 VBA 进销存的业务逻辑经验,但不想再继续维护复杂的宏代码,可以考虑将需求迁移到低代码平台或云端模板系统中,例如:
- 使用基于表单+流程的进销存模版;- 用可视化字段配置替代手写表结构;- 用流程引擎替代 VBA 中复杂的审批流与状态机。
这类平台通常可以让你在 Web 端设计「商品、客户、库存、单据」等表单,再拖拽搭建流程。对于习惯 Excel 的用户,上手也不算难。
在云端进销存工具中,「简道云进销存」这种基于在线表单+报表+流程的系统模板,在设计理念上与 VBA 进销存类似:同样围绕商品、入库、出库、库存台账、报表这套逻辑,只是把 VBA 脚本换成了可视化配置与云端自动化执行。对于希望逐步摆脱 Excel 但又想延续原有进销存思路的团队,这是一个较平滑的迁移方向。
---
## 🔮 十一、总结与未来趋势:从 VBA 进销存走向数字化运营
VBA 制作进销存系统,是很多中小团队实现数字化库存管理的第一步。通过本文的完整攻略,你可以在 Excel 中构建一套较完整的进销存解决方案,包括:
- 梳理业务流程:采购、销售、库存、报表;- 设计数据结构:商品档案、库存台账、库存汇总;- 使用 VBA 实现核心逻辑:库存加减、单号生成、库存预警;- 构建自动报表:销售统计、采购统计、库存预警;- 做基础权限、日志与备份控制,提高进销存系统的可靠性。
从趋势来看:
1. **轻量级进销存仍然有 VBA 的用武之地**对于个人卖家、小微商户、单店或单仓业务,VBA 进销存依然是成本极低、可快速起步的方式,尤其是在企业尚未确定长期系统方案时,可以作为原型与过渡工具。
2. **多端协同与云端化是大势所趋**随着业务复杂度提升、团队协作需求增强、远程办公普及,本地 Excel + VBA 进销存会逐渐暴露出「协同、权限、审计、扩展性」方面的短板,迁移到云端系统会成为大多数企业的自然选择。
3. **低代码/模板化进销存会越来越流行**企业更愿意采用「可配置」而非「从零开发」的方式来搭建进销存系统。通过使用成熟的模板和可视化配置工具,可以减少对特定 VBA 开发人员的依赖,让业务部门自己掌控库存管理流程。
在实践中,你完全可以先用 VBA 进销存打磨流程、校验规则和报表逻辑;当业务稳定后,再把这些成熟经验迁移到云端平台或专业系统中。这样既节省了前期投入,也兼顾了长期扩展性。
---
最后分享一个我们公司在用的进销存系统模板,需要的可以自取,可直接使用,也可以自定义编辑修改:https://s.fanruan.com/8bn69
这类基于在线表单与流程的进销存模板,在思路上与 VBA 进销存高度相通,对于已经习惯 Excel 逻辑的同学,会是一个比较顺滑的升级方向。
## 精品问答:---
<div class="faq"> <div class="q"> VBA制作进销存系统的核心功能有哪些?</div><div class="subq"> 我刚开始接触VBA,想用它来制作一个进销存系统,但不太清楚核心功能应该包括哪些内容。有哪些关键模块是必须实现的?</div><div class="a"> VBA制作进销存系统的核心功能主要包括库存管理、采购管理、销售管理和报表生成。具体功能如下:
1. 库存管理:实时更新库存数量,自动提醒库存不足。2. 采购管理:录入采购订单,自动增加库存。3. 销售管理:记录销售订单,自动减少库存。4. 报表生成:自动生成库存状态、采购和销售报表,支持导出Excel。
例如,通过VBA代码实现库存自动更新,可以减少人为错误,提升管理效率。根据行业调研,完善的库存管理系统能提升库存准确率达95%以上。</div></div><div class="faq"> <div class="q"> 如何用VBA快速上手制作进销存系统?</div><div class="subq"> 我对VBA不太熟悉,想知道有没有快速上手的方法或步骤,能帮助我快速用VBA制作一个简单的进销存管理系统?</div><div class="a"> 快速上手制作VBA进销存系统,可以遵循以下步骤:
1. 明确需求:列出需管理的商品、采购和销售流程。2. 设计数据结构:创建Excel表格存储商品信息、采购单、销售单。3. 编写VBA宏:实现数据录入、库存自动计算和报表生成。4. 分步测试:确保每个模块功能正确。
案例:初学者可先实现简单的库存加减功能,再逐步增加采购和销售管理模块。平均学习时间约为2-3周,结合实操效果最佳。</div></div><div class="faq"> <div class="q"> VBA进销存系统中如何实现库存自动预警?</div><div class="subq"> 我担心库存管理时,无法及时发现库存不足的问题。有没有办法用VBA实现库存自动预警功能?这样能否避免断货风险?</div><div class="a"> VBA进销存系统中,库存自动预警可通过设置库存阈值实现。具体做法:
1. 在商品库存表中新增“最低库存”字段。2. 利用VBA循环检测库存数量,若低于阈值,则弹出提示或发送邮件通知。3. 结合条件格式,库存不足的商品单元格高亮显示。
例如,某企业采用此方法后,库存断货率降低了40%,有效保障生产和销售连续性。</div></div><div class="faq"> <div class="q"> 如何用VBA提高进销存系统的数据准确性?</div><div class="subq"> 我发现手工录入数据容易出错,想知道用VBA制作的进销存系统如何确保数据的准确性和一致性?</div><div class="a"> 用VBA提高进销存系统数据准确性,可以采取以下措施:
1. 输入校验:使用VBA代码限制输入格式,如数字范围、日期格式。2. 自动计算:减少手工计算,避免运算错误。3. 数据关联:建立采购、销售与库存数据的关联,自动同步更新。4. 错误提示:出现异常数据时,弹出提示框提醒用户。
例如,设置采购数量必须为正整数,若输入错误,系统立即提示,显著减少录入错误率,提升整体数据质量。</div></div>
<div class="social-share-container"> <div class="like-container"> <button id="likeButton" class="like-button"> <i width="28" height="28" class="svgicon"><svg class="good_svg__icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="28" height="28"><path d="M204.76 450.82c-17.67 0-32 14.33-32 32v336c0 17.67 14.33 32 32 32s32-14.33 32-32v-336c0-17.67-14.32-32-32-32zm646.29 65.53c-1.99-26.2-9.51-42.57-16.54-52.4-5.95-8.31-15.63-13.13-25.85-13.13H624.08l42.13-158.9c19.63-73.61-39.84-104.83-39.84-104.83-18.86-10.07-35.6-13.9-50.15-13.9-46.02 0-70.14 38.29-70.14 38.29-81.14 151.41-158.97 211.36-190.85 231.08a31.962 31.962 0 00-15.13 27.19v348.56c0 17.67 14.33 32 32 32h394.35c13.94 0 26.28-9.03 30.5-22.31l91.28-287.38a64.195 64.195 0 002.82-24.27z"></path></svg></i> <span id="likeCount">211</span> </button> </div>
<div class="social-buttons"> <button class="social-button wechat" title="分享到微信"> <i width="28" height="28" class="svgicon"><svg class="wechat_svg__icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="28" height="28"><defs><style></style></defs><path d="M923.093 656.17c0-116.095-116.053-210.645-246.613-210.645-138.325 0-246.997 94.55-246.997 210.646 0 116.352 108.672 210.56 246.997 210.56 28.928 0 58.197-7.382 87.125-14.422L843.35 896l-21.845-72.661c58.197-43.691 101.59-101.888 101.59-167.168zM596.352 619.82c-14.421 0-28.885-14.464-28.885-28.971 0-14.421 14.464-28.885 28.885-28.885 21.888 0 36.395 14.506 36.395 28.885 0 14.507-14.507 28.97-36.395 28.97zm159.872 0c-14.464 0-28.885-14.464-28.885-28.971 0-14.421 14.421-28.885 28.885-28.885 21.845 0 36.352 14.506 36.352 28.885 0 14.507-14.848 28.97-36.352 28.97zm-103.68-199.936c9.472 0 19.03.64 28.501 1.621-25.6-119.552-153.258-208.17-299.136-208.17-162.901 0-296.576 110.975-296.576 252.16 0 81.493 44.374 148.48 118.571 200.362l-29.568 89.301 103.765-52.181c37.12 7.21 66.987 14.763 103.808 14.763 9.174 0 18.39-.342 27.606-1.28a216.619 216.619 0 01-9.216-62.08c0-129.408 111.36-234.496 252.202-234.496zm-159.659-80.47c22.315 0 37.12 14.806 37.12 37.12s-14.805 37.12-37.12 37.12c-22.357 0-44.672-14.805-44.672-37.12.342-22.357 22.614-37.12 44.672-37.12zm-207.53 74.198c-22.358 0-44.672-14.763-44.672-37.12 0-22.315 22.314-37.12 44.672-37.12 22.357 0 37.12 14.805 37.12 37.12 0 22.016-14.763 37.12-37.12 37.12z"></path></svg></i> </button> <button class="social-button weibo" title="分享到微博"> <i width="28" height="28" class="svgicon"><svg class="weibo_svg__icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="28" height="28"><defs><style></style></defs><path d="M716.544 502.955c-33.11-6.4-17.024-24.32-17.024-24.32s32.427-53.59-6.4-92.587c-48.17-48.299-165.248 6.101-165.248 6.101-44.715 13.867-32.81-6.4-26.539-40.832 0-40.618-13.866-109.354-132.906-68.736C249.6 323.371 147.37 466.475 147.37 466.475 76.373 561.408 85.76 634.88 85.76 634.88c17.75 162.09 189.525 206.592 323.2 217.173 140.587 11.008 330.325-48.64 387.84-171.093 57.6-122.837-46.976-171.35-80.256-178.005zm-297.13 303.274c-139.649 6.571-252.417-63.658-252.417-157.013 0-93.44 112.768-168.405 252.416-174.848 139.606-6.443 252.672 51.243 252.672 144.512 0 93.44-113.066 181.035-252.672 187.35zm-27.862-270.25c-140.288 16.469-124.075 148.309-124.075 148.309s-1.493 41.685 37.675 62.976c82.133 44.63 166.656 17.579 209.45-37.675 42.582-55.381 17.494-190.037-123.05-173.653zM356.139 720.98c-26.198 3.158-47.36-12.074-47.36-34.048 0-21.888 18.73-44.8 45.013-47.573 30.037-2.816 49.664 14.55 49.664 36.523 0 21.888-21.163 42.069-47.36 45.098zm82.773-70.656c-8.875 6.614-19.797 5.76-24.49-2.261a20.693 20.693 0 015.973-26.752c10.325-7.808 21.162-5.547 25.856 2.219 4.693 7.936 1.28 19.925-7.339 26.794zm345.984-204.501a22.912 22.912 0 0022.827-21.76c17.194-154.581-126.251-127.915-126.251-127.915a23.04 23.04 0 00-22.955 23.254c0 12.672 10.155 23.04 22.955 23.04 102.997-22.87 80.341 80.469 80.341 80.469a22.87 22.87 0 0023.04 22.912zm-16.725-269.653c-49.579-11.648-100.566-1.579-114.902 1.152-1.109.085-2.133 1.152-3.157 1.365-.47.085-.768.597-.768.597a33.707 33.707 0 009.088 66.091s18.048-2.432 30.293-7.253c12.075-4.864 114.774-3.584 165.888 82.261 27.819 62.677 12.203 104.661 10.24 111.36 0 0-6.656 16.341-6.656 32.341 0 18.56 14.848 30.166 33.28 30.166 15.446 0 28.459-2.134 32.171-28.16h.17c54.87-183.211-66.9-269.227-155.647-289.963z"></path></svg></i> </button> <button class="social-button qzone" title="分享到QQ空间"> <i width="28" height="28" class="svgicon"><svg class="qzone_svg__icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="28" height="28"><path d="M943.373 399.728c-3.291-10.108-15.57-33.986-58.66-37.438l-181.825-14.575c-25.37-2.035-57.362-25.28-67.12-48.763l-70.056-168.423c-16.6-39.899-43.101-44.206-53.73-44.206-10.621 0-37.123 4.307-53.723 44.212l-70.05 168.422c-9.775 23.49-41.762 46.729-67.114 48.765l-181.833 14.575c-43.077 3.456-55.362 27.329-58.647 37.437s-7.373 36.649 25.44 64.759l138.54 118.671c19.315 16.564 31.536 54.161 25.636 78.91l-42.32 177.424c-7.26 30.454.557 48.68 8.399 58.611 9.019 11.427 22.411 17.712 37.703 17.712 12.781 0 26.517-4.427 40.827-13.179l155.676-95.077c10.25-6.26 25.754-9.99 41.484-9.99 15.736 0 31.24 3.734 41.478 9.99l155.7 95.077c14.298 8.752 28.028 13.18 40.804 13.18v-.012H750c15.28 0 28.671-6.292 37.685-17.731 7.836-9.93 15.659-28.145 8.403-58.593l-41.904-175.65c-32.757 1.32-68.18 1.989-105.74 1.989-128.402 0-239.552-7.71-244.22-8.03a26.778 26.778 0 01-18.436-9.22 26.826 26.826 0 01-6.527-19.565 26.767 26.767 0 0114.275-21.89c2.982-1.603 72.115-38.62 157.86-98.491l22.617-15.795-27.488-2.48c-34.685-3.13-74.287-4.722-117.701-4.722-55.955 0-98.171 2.682-98.574 2.71a27.004 27.004 0 01-28.59-25.122 26.95 26.95 0 0125.11-28.618c1.805-.118 44.84-2.889 101.58-2.889 62.801 0 151.433 3.428 217.057 19.738a26.761 26.761 0 0116.588 12.25 26.802 26.802 0 013.053 20.38 27.015 27.015 0 01-9.587 14.753c-41.017 31.916-84.944 63.05-130.578 92.539l-27.039 17.463 32.17 1.053c41.573 1.356 81.88 2.037 119.78 2.037 39.88 0 77.173-.763 111.112-2.28 4.704-10.656 11.062-20.138 18.488-26.505L917.92 464.476c32.814-28.105 28.732-54.646 25.453-64.748z" fill="#currentColor"></path></svg></i> </button> <button class="social-button copy-link" title="复制链接"> <i width="28" height="28" class="svgicon"><svg class="link_svg__icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="28" height="28"><path d="M369.067 594.773l225.706-225.706a21.333 21.333 0 0130.294 0l29.866 29.866a21.333 21.333 0 010 30.294L429.227 654.933a21.333 21.333 0 01-30.294 0l-29.866-29.866a21.333 21.333 0 010-30.294zM896 326.827v14.506a170.667 170.667 0 01-50.347 121.174l-120.32 120.746a57.6 57.6 0 01-81.066 0L640 578.56a21.333 21.333 0 010-29.867L786.773 401.92a85.333 85.333 0 0023.894-60.587v-14.506a85.333 85.333 0 00-25.174-60.587l-27.733-27.733a85.333 85.333 0 00-60.587-25.174h-14.506a85.333 85.333 0 00-60.587 25.174L475.307 384a21.333 21.333 0 01-29.867 0l-4.693-4.693a57.6 57.6 0 010-81.067l120.746-121.173A170.667 170.667 0 01682.667 128h14.506a170.667 170.667 0 01120.747 49.92l28.16 28.16A170.667 170.667 0 01896 326.827zM548.693 640a21.333 21.333 0 0129.867 0l4.693 4.693a57.6 57.6 0 010 81.067l-121.6 121.6A170.667 170.667 0 01341.333 896h-14.506a170.667 170.667 0 01-120.747-49.92l-28.16-28.16A170.667 170.667 0 01128 697.6v-14.933a170.667 170.667 0 0150.347-121.174l120.32-120.746a57.6 57.6 0 0181.066 0l4.694 4.693a21.333 21.333 0 010 29.867L238.507 622.08a85.333 85.333 0 00-25.174 60.587v14.506a85.333 85.333 0 0025.174 60.587l27.733 27.733a85.333 85.333 0 0060.587 25.174h14.506a85.333 85.333 0 0061.014-25.174z"></path></svg></i> </button> </div></div>
<div id="wechatModal" class="modal"> <div class="modal-content"> <span class="close">×</span> <p>微信分享</p> <div id="qrcode-placeholder" class="qrcode-placeholder"></div> <p>扫描二维码分享到微信</p> </div></div><script id="sidebarHtml" src="https://www.jiandaoyun.com/nblog/js/sidebarHtml.js"></script><script id="clickA" src="https://nblog.jdycdn.com/js/clickA.js"></script><script src="https://nblog.jdycdn.com/js/qrcode.min.js"></script><script id="share" src="https://nblog.jdycdn.com/js/share.js"></script><script src="https://nblog.jdycdn.com/js/nav.js"></script>
文章版权归"
转载请注明出处:https://www.jiandaoyun.com/nblog/493702/
温馨提示:文章由AI大模型生成,如有侵权,联系 mumuerchuan@gmail.com
删除。