在数据库管理系统中,尤其是对于一些基础资料,可能并不仅仅是文字信息,还可能带有相应的附件(尤其是图片)。对于这种情况,我们的通常做法是将文件放在共享服务器上,然后在数据库中仅记录相应的文件路径,需要的时候通过程序自动调用并进行管理维护。基于该实现思路,快速开发平台提供了一个通用的附件管理模块,让你不必再为附件的添加、修改、删除、查看等功能的实现费脑筋,而只需要简单的调用即可。
该附件管理模块可以和任意数据表进行结合,对一个数据表甚至还可以进行多重展示(例如产品是机器,需要将部件分别管理)。
效果预览
附件服务器类型
可以系统设置中进行设置,支持共享文件夹和FTP服务器两种附件存储方式。
注:企业版平台才能使用FTP服务器存储附件,免费版和专业版平台不支持。
使用方法
通用附件模块以子窗体形式使用,只需要在编辑窗体中添加一个子窗体控件,将其“源对象”属性设为“SysFrmAttachments”,然后调用其接口即可。
接口说明
初始化及加载附件:LoadAttachment ( ATForm, DataCategory, DataID[, ActiveConnection][, Delimiter1 = "\"][, Delimiter2 = " "] )
- ATForm必需的。附件子窗体对象,可以是 Subform 类型,也可以是 Form 类型。
- DataCategory 必需的。和数据表相关的标识,比如“产品表”该参数可以设为“产品照片”,“员工表”该参数可以设为“员工照片”等 。可以任意指定,但一旦确定了就不能改,否则可能会导致数据和文件无法关联!
- DataID 必需的。设为数据表中的唯一标识 ID 字段的值,如“产品表”该参数对应“产品编号”字段,“员工表”该参数对应“工号”字段。新增模式下可以为Null,该值同样一旦确定就不能改,否则可能会导致数据和文件无法关联!
- ActiveConnection 可选的。活动的 ADO 连接。当保存数据使用了事务处理时,需要该参数。
- Delimiter1 可选的。DataCategory 和 DataID 之间使用的分隔符。
- Delimiter2 可选的。DataID 和附件文件名之间使用的分隔符。
保存附件:SaveAttachment ( ATForm, DataID[, ActiveConnection] )
- ATForm必需的。附件子窗体对象,可以是 Subform 类型,也可以是 Form 类型。
- DataID 必需的。数据ID,一般使用数据表的主键字段的值。
- ActiveConnection 可选的。活动连接。当保存数据使用了事务处理时,需要该参数。
删除指定数据关联附件:SaveAttachment ( DataCategory, DataID[, ActiveConnection][, Delimiter1 = "\"][, Delimiter2 = " "] )
- DataCategory 必需的。数据分类,用于对附件进行分类。
- DataID 必需的。数据ID,一般使用数据表的主键字段的值。
- ActiveConnection 可选的。活动连接。当保存数据使用了事务处理时,需要该参数。
- Delimiter1 可选的。DataCategory 和 DataID 之间使用的分隔符。
- Delimiter2 可选的。DataID 和附件文件名之间使用的分隔符。
设置附件模块界面颜色样式:ThemeColor
如何修改分隔符参数 Delimiter1 和 Delimiter2 的默认值?
进入 basRDPRef 模块,将其中的 LoadAttachment 和 DeleteAttachment 两个接口函数中,Delimiter1 和 Delimiter2 参数的默认值修改为想要的值即可。
新旧两种接口差异对比
'新版调用示例 LoadAttachment Me.sfrAttachments, "商品照片", Me!商品ID SaveAttachment Me.sfrAttachments, Me!商品ID DeleteAttachment "商品照片", Me.sfrList!商品ID '旧版调用示例 Call Me.sfrAttachments.Form.LoadAttachmentData("商品照片", Me!商品ID, cnn) Call Me.sfrAttachments.Form.SaveAttachmentData("商品照片", Me!商品ID, cnn) 差异: 1. 旧版接口是在附件子窗体类模块中的函数,新版接口是全局函数。 2. 旧版没有删除功能,新版有。 3. 旧版接口函数名有Data字样,新版没有(主要是为了进行区分)。 4. 旧版的保存附件(SaveAttachment)需要指定 DataCategory 参数,新版无此参数,直接使用附件加载时(LoadAttachment)指定的 DataCategory 参数。 5. 新版强制要求无论是新增模式还是修改模式,都要调用 LoadAttachment 进行初始化,旧版无此要求。 6. 旧版默认使用“-”作为分隔符,新版默认使用“\”和“ ”(空格)作为分隔符。 7. 由于分隔符的不同,旧版所有附件均在一个目录下,而新版会根据 DataCategory 创建不同的子目录。
示例(新的方式,推荐使用)
Public Function InitData() ClearControlValues Me '--------------------------------------------------------------------------------------------- '由于新增模式下保存后Edit窗体不会关闭,所以这里需要再次调用进行重新初始化 LoadAttachment Me.sfrAttachments, "商品照片", Me!商品ID '“商品照片”不能为变量 LoadAttachment Me.sfrAttachments2, "商品照片_旧款", Me!商品ID '“商品照片_旧款”不能为变量 '--------------------------------------------------------------------------------------------- End Function Private Sub Form_Load() On Error GoTo ErrorHandler Dim cnn: Set cnn = CurrentProject.Connection '编辑窗体的其它加载事件代码,此处省略 If Nz(Me.OpenArgs) <> "" Then LoadRecord Me, "SELECT * FROM 商品信息表 WHERE 商品代码='" & Me.OpenArgs & "'" '再次强调,LoadAttachment 不能在这里调用! End If ' '--------------------------------------------------------------------------------------------- '通过这一行代码的调用实现附件的加载 '不论是新增还是修改,都要调用 LoadAttachment 函数,因为它不光是用来加载已有附件,还用来对附件窗体进行初始化处理。 '第1个参数 Category (即下方的"商品照片")必须是一个固定不变的字符串,一般可以用功能模块的名称,不能是变量,否则一旦变化就会导致数据和附件关联不上! '第2个参数 DataID 应该取数据的主键,即能确定数据唯一性的值。最好是一生成就不会被修改的值,否则也可能导致数据和附件关联不上! '第3个参数 ActiveConnection 如果没有可以省略,默认使用CurrentProject.Connection LoadAttachment Me.sfrAttachments, "商品照片", Me!商品ID '“商品照片”不能为变量 '使用不同的子窗体,并且这里第一个参数设成不一样,可以实现多重展示,即同时可以显示多个图片 LoadAttachment Me.sfrAttachments2, "商品照片_旧款", Me!商品ID '“商品照片_旧款”不能为变量 '--------------------------------------------------------------------------------------------- ExitHere: Exit Sub ErrorHandler: MsgBoxEx Err.Description, vbCritical Resume ExitHere End Sub Private Sub btnSave_Click() On Error GoTo ErrorHandler Dim cnn: Set cnn = CurrentProject.Connection '编辑窗体的其它保存按钮单击事件代码,此处省略 '--------------------------------------------------------------------------------------------- '通过这一行代码的调用实现附件的保存 SaveAttachment Me.sfrAttachments, Me!商品ID, cnn '“商品照片”不能为变量 '多重展示时,将第二个子窗体的数据也进行保存 SaveAttachment Me.sfrAttachments2, Me!商品ID, cnn '“商品照片_旧款”不能为变量 '--------------------------------------------------------------------------------------------- RequeryDataObject gsfrList MsgBoxEx "保存成功!", vbInformation If Me.DataEntry Then Me.InitData Else DoCmd.Close acForm, Me.Name, acSaveNo End If ExitHere: Set rst = Nothing Set cnn = Nothing Exit Sub ErrorHandler: MsgBoxEx Err.Description, vbCritical Resume ExitHere End Sub
示例(旧的方式,保留用于兼容,不建议再继续使用)
Public Function InitData() ClearControlValues Me '--------------------------------------------------------------------------------------------- '由于新增模式下保存后Edit窗体不会关闭,所以这里需要再次调用进行重新初始化 Call Me.sfrAttachments.Form.LoadAttachmentData("商品照片", Me!商品ID)'“商品照片”不能为变量 Call Me.sfrAttachments2.Form.LoadAttachmentData("商品照片_旧款", Me!商品ID) '“商品照片_旧款”不能为变量 '--------------------------------------------------------------------------------------------- End Function Private Sub Form_Load() On Error GoTo ErrorHandler Dim cnn: Set cnn = CurrentProject.Connection '编辑窗体的其它加载事件代码,此处省略 If Nz(Me.OpenArgs) <> "" Then LoadRecord Me, "SELECT * FROM 商品信息表 WHERE 商品代码='" & Me.OpenArgs & "'" '再次强调,LoadAttachmentData 不能在这里调用! End If ' '--------------------------------------------------------------------------------------------- '通过这一行代码的调用实现附件的加载 '不论是新增还是修改,都要调用 LoadAttachmentData 函数,因为它不光是用来加载已有附件,还用来对附件窗体进行初始化处理。 '第1个参数 Category (即下方的"商品照片")必须是一个固定不变的字符串,一般可以用功能模块的名称,不能是变量,否则一旦变化就会导致数据和附件关联不上! '第2个参数 DataID 应该取数据的主键,即能确定数据唯一性的值。最好是一生成就不会被修改的值,否则也可能导致数据和附件关联不上! '第3个参数 ActiveConnection 如果没有可以省略,默认使用CurrentProject.Connection Call Me.sfrAttachments.Form.LoadAttachmentData("商品照片", Me!商品ID) '“商品照片”不能为变量 '使用不同的子窗体,并且这里第一个参数设成不一样,可以实现多重展示,即同时可以显示多个图片 Call Me.sfrAttachments2.Form.LoadAttachmentData("商品照片_旧款", Me!商品ID) '“商品照片_旧款”不能为变量 '--------------------------------------------------------------------------------------------- ExitHere: Exit Sub ErrorHandler: MsgBoxEx Err.Description, vbCritical Resume ExitHere End Sub Private Sub btnSave_Click() On Error GoTo ErrorHandler Dim cnn: Set cnn = CurrentProject.Connection '编辑窗体的其它保存按钮单击事件代码,此处省略 '--------------------------------------------------------------------------------------------- '通过这一行代码的调用实现附件的保存 Call Me.sfrAttachments.Form.SaveAttachmentData("商品照片", Me!商品ID, cnn) '“商品照片”不能为变量 '多重展示时,将第二个子窗体的数据也进行保存 Call Me.sfrAttachments2.Form.SaveAttachmentData("商品照片_旧款", Me!商品ID, cnn) '“商品照片_旧款”不能为变量 '--------------------------------------------------------------------------------------------- RequeryDataObject gsfrList MsgBoxEx "保存成功!", vbInformation If Me.DataEntry Then Me.InitData Else DoCmd.Close acForm, Me.Name, acSaveNo End If ExitHere: Set rst = Nothing Set cnn = Nothing Exit Sub ErrorHandler: MsgBoxEx Err.Description, vbCritical Resume ExitHere End Sub
修订记录
加入版本:v2.0.1
2021-06-03 v2.6.0 增加 FTP 支持,可将附件保存到 FTP 服务器上。
2021-08-14 v2.6.2.505 完善示例代码。
2021-09-25 v2.6.3.518 全新升级。
2021-12-03 v2.6.5.547 修改了示例代码,并增加了自定义默认参数的说明。
2022-05-05 v2.6.6.558 文档修订。