第23步:自定义格式器

自定义格式器实现数据模型属性的本地化

说明

如果我们想用更复杂的逻辑来格式化数据模型的属性,我们还可以编写自定义格式化函数。现在,我们将使用自定义格式化程序添加本地化状态,因为数据模型中的状态是一种技术性很强的格式。


预览

在这里插入图片描述

状态现在用自定义格式化程序显示了

代码

你可以在演练-第23步查看和下载所有文件。

webapp/model/formatter.js (New)

sap.ui.define([], function () {
	"use strict";
	return {
		statusText: function (sStatus) {
			var resourceBundle = this.getView().getModel("i18n").getResourceBundle();
			switch (sStatus) {
				case "A":
					return resourceBundle.getText("invoiceStatusA");
				case "B":
					return resourceBundle.getText("invoiceStatusB");
				case "C":
					return resourceBundle.getText("invoiceStatusC");
				default:
					return sStatus;
			}
		}
	};
});

我们在应用程序项目中创建一个新的文件夹model。新的格式化程序文件被放置在应用程序的model文件夹中,因为格式化程序正在处理数据属性并格式化它们以便在UI上显示。到目前为止,我们还没有任何模型相关的工件,除了Invoices.json文件,我们现在将webapp/model文件夹添加到我们的应用程序中。这一次,我们没有从任何基对象扩展,只是返回一个JavaScript对象,其中包含sap.ui.define调用中的格式化器函数。

函数statusText从数据模型获取技术状态作为输入参数,并返回从resourceBundle文件读取的人类可读的文本。

webapp/controller/InvoiceList.controller.js
在这里插入图片描述

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/model/json/JSONModel",
	"../model/formatter"
], function (Controller, JSONModel, formatter) {
	"use strict";
	return Controller.extend("sap.ui.demo.walkthrough.controller.InvoiceList", {
		formatter: formatter,
		onInit : function () {
			var oViewModel = new JSONModel({
				currency: "EUR"
			});
			this.getView().setModel(oViewModel, "view");
		}
	});
});

要加载格式化程序函数,必须将其添加到InvoiceList.controller.js中。在这个控制器中,我们首先向自定义formatter模块添加一个依赖项。控制器只是将加载的格式化器函数存储在本地属性格式化器中,以便能够在视图中访问它们。

webapp/view/InvoiceList.view.xml
在这里插入图片描述

<mvc:View
	controllerName="sap.ui.demo.walkthrough.controller.InvoiceList"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc">
	<List
			headerText="{i18n>invoiceListTitle}"
		class="sapUiResponsiveMargin"
		width="auto"
		items="{invoice>/Invoices}">
		<items>
			<ObjectListItem
				title="{invoice>Quantity} x {invoice>ProductName}"
				number="{
					parts: [{path: 'invoice>ExtendedPrice'}, {path: 'view>/currency'}],
					type: 'sap.ui.model.type.Currency',
					formatOptions: {
						showMeasure: false
					}
				}"
				numberUnit="{view>/currency}"
				numberState="{=	${invoice>ExtendedPrice} > 50 ? 'Error' : 'Success' }">
				<firstStatus>
					<ObjectStatus text="{
						path: 'invoice>Status',
						formatter: '.formatter.statusText'
					}"/>
				</firstStatus>
			</ObjectListItem>
		</items>
	</List>
</mvc:View>

我们使用firstStatus聚合向objectisttitem添加一个状态,该状态将显示发票的状态。使用绑定语法的预留属性格式化器指定自定义格式化器函数。格式化程序名称前面的 “.” 表示在当前视图的控制器中查找该函数。在那里,我们定义了一个属性formatter,它保存了我们的formatter函数,因此我们可以通过.formatter.statusText访问它。

webapp/i18n/i18n.properties
在这里插入图片描述

# App Descriptor
appTitle=Hello World
appDescription=A simple walkthrough app that explains the most important concepts of SAPUI5

# Hello Panel
showHelloButtonText=Say Hello
helloMsg=Hello {0}
homePageTitle=Walkthrough
helloPanelTitle=Hello World
openDialogButtonText=Say Hello With Dialog
dialogCloseButtonText=Ok

# Invoice List
invoiceListTitle=Invoices
invoiceStatusA=New
invoiceStatusB=In Progress
invoiceStatusC=Done

我们向资源包中添加三个新条目,以反映翻译后的状态文本。这些文本现在根据发票的状态显示在objectistitem的number属性下面。

章节

  1. 第1步:你好世界
  2. 第2步:引导
  3. 第3步:控件
  4. 第4步:XML视图
  5. 第5步:控制器
  6. 第6步:模块
  7. 第7步:JSON模型
  8. 第8步:可翻译的文本
  9. 第9步:组件配置
  10. 第10步:应用程序描述符
  11. 第11步:页面和面板
  12. 第12步:Shell控件作为容器
  13. 第13步:外边距和内边距
  14. 第14步:自定义CSS和主题颜色
  15. 第15步:嵌套视图
  16. 第16步:对话框和片段
  17. 第17步:片段回调
  18. 第18步:图标
  19. 第19步:重用对话框
  20. 第20步:聚合绑定
  21. 第21步:数据类型
  22. 第22步:表达式绑定
  23. 第23步:自定义格式器
  24. 第24步:过滤
  25. 第25步:排序和分组
  26. 第26步:远程OData服务
  27. 第27步:模拟服务器配置
  28. 第28步:使用QUnit进行单元测试
  29. 第29步:与OPA的集成测试
  30. 第30步:调试工具
  31. 第31步:路由和导航
  32. 第32步:路由与参数
  33. 第33步:路由回溯和历史
  34. 第34步:自定义控件
  35. 第35步:响应性
  36. 第36步:设备适应
  37. 第37步:内容密度
  38. 第38步:可访问性
用VB宏语言完成以下任务并在代码中明确标注每一的作用,我会在每一次提问中不断更新修正需求: 第一:从三个可自定义选择的工作簿中选中名为“明细表”的工作表 第二:从三个明细表中选中与A列中填写内容为数字(如1,2,3等)所对应的C列的人名 第三:将三个明细表内选中的人名去除重复的,每一个人名仅保留一次 第四:以这些人名为每个对应工作表的名字建立一个工作簿(该工作簿可自定义保存路径和命名,后续为便于理解将该工作簿称为工作簿X) 第五:将工作簿X每一个工作表的A3,A4格合并为一个并填入内容“序号”,将工作簿X个工作表的B3,B4格合并为一个并填入内容“工作类别” 第六:将工作簿X每一个工作表在第4行从C4开始填入第四个可指定工作簿(为方便区分将该工作簿称为工作簿H1)中从D5开始到该行“现场办公(天)”(不包含填入该内容)前的内容结束(可对填入的内容进行检查,本次填入的内容仅包含数字) 第七:在第六完成后,将工作簿X每一个工作表从C3格开始到对应刚刚第4行最后输入的列所对应的第三行的格为一个单元格,并填入内容“工时统计记录”;在工时统计记录格后一格合并其第3行和第4行对应格,在该格子内填入内容“项目占比工时” 第八:回溯将工作簿X每一个工作表的名字都在哪几个明细表中出现,将名字出现过的明细表的A2格内的内容按第二自定义选中的顺序填入将工作簿X对应工作表的从B列开始的B5格,依次往下; 第九:在第八填入完成后,每一个在B列最后以后已填内容后的下个格子内填入“经营工作”,在“经营工作”后的下一个格子内填入“合计” 第十:对工作簿H1的C列C5格子后的内容进行筛选,筛选出工作簿X的对应工作表名字,将工作簿H1该名字所在行的从D列到第五行内容“现场办公(天)”所在列为止(不包含“现场办公(天)”所在列)的内容填入工作簿X的对应人名工作表的“合计”格后 第十一:将合计格后填入的内容中的“PX”、“K”、“=”替换为“8”
最新发布
09-02
<think> 我们正在处理一个涉及Excel VBA宏的任务。用户需求总结如下: 1. 从三个自定义工作簿的明细表中提取人名(假设每个工作簿中都有一个名为“明细表”的工作表) 2. 对提取的人名进行去重 3. 创建一个新的工作簿 4. 在新的工作簿中设置工作表格式(包括填入特定内容、筛选和替换数据等) 骤分解: 1. 打开三个源工作簿(假设用户会提供路径或通过文件选择对话框选择) 2. 遍历每个源工作簿的“明细表”工作表,提取人名(假设人名在某一列,例如A列,但具体列需要用户指定或我们假设为A列) 3. 将所有提取的人名合并到一个集合(Collection)或字典(Dictionary)中以便去重 4. 创建一个新的工作簿 5. 在新工作簿的活动工作表中设置格式(可能包括列标题、行高、列宽、字体等) 6. 将去重后的人名列表写入新工作簿的指定位置(例如A列) 7. 进行其他数据处理:如筛选、替换等(需要更具体的需求,但用户没有详细说明,我们可以给出一个通用示例) 8. 保存新工作簿 由于用户需求中没有给出非常具体的细节(如人名所在的列、格式设置的具体要求等),我们将提供一个大致的框架,用户可以根据实际情况调整。 注意事项: - 使用字典对象去重,需要先引用“Microsoft Scripting Runtime”或者使用后期绑定。 - 假设三个源工作簿已经打开,或者通过路径打开。这里我们假设通过路径打开,路径由用户提供或通过文件选择对话框选择。 代码框架: ```vb Sub ExtractAndProcessNames() Dim sourceWorkbookPaths(1 To 3) As String Dim sourceWorkbooks(1 To 3) As Workbook Dim dict As Object ' 用于去重 Dim nameCollection As Collection Dim newWorkbook As Workbook Dim destinationSheet As Worksheet Dim sourceSheet As Worksheet Dim cell As Range Dim lastRow As Long Dim i As Integer, j As Integer Dim nameValue As Variant ' 设置三个源工作簿的路径(实际使用中可能需要通过文件选择对话框获取) sourceWorkbookPaths(1) = "C:\Path\To\Workbook1.xlsx" sourceWorkbookPaths(2) = "C:\Path\To\Workbook2.xlsx" sourceWorkbookPaths(3) = "C:\Path\To\Workbook3.xlsx" ' 初始化字典(使用后期绑定) Set dict = CreateObject("Scripting.Dictionary") ' 遍历三个工作簿 For i = 1 To 3 ' 打开工作簿 Set sourceWorkbooks(i) = Workbooks.Open(sourceWorkbookPaths(i)) Set sourceSheet = sourceWorkbooks(i).Sheets("明细表") ' 假设工作表名为"明细表" ' 假设人名在A列,从第2行开始(第1行是标题) lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row For j = 2 To lastRow nameValue = sourceSheet.Cells(j, 1).Value ' 第1列(A列) If nameValue <> "" Then ' 使用字典去重(不区分大小写?这里区分,如需不区分,可转换为统一大小写) If Not dict.Exists(nameValue) Then dict.Add nameValue, nameValue End If End If Next j ' 关闭源工作簿(不保存更改) sourceWorkbooks(i).Close SaveChanges:=False Next i ' 创建新工作簿 Set newWorkbook = Workbooks.Add Set destinationSheet = newWorkbook.Sheets(1) destinationSheet.Name = "去重后名单" ' 写入标题 destinationSheet.Cells(1, 1).Value = "姓名" ' 将字典中的键(去重后的姓名)写入新工作簿 Dim names As Variant names = dict.Keys For i = 0 To dict.Count - 1 destinationSheet.Cells(i + 2, 1).Value = names(i) Next i ' 设置格式(示例:自动调整列宽,设置字体等) destinationSheet.Columns(1).AutoFit destinationSheet.Rows(1).Font.Bold = True ' 其他数据处理(根据用户需求,这里仅做示例) ' 示例1:筛选出姓“张”的人名(假设需要,这里使用自动筛选) ' destinationSheet.Range("A1").AutoFilter Field:=1, Criteria1:="张*" ' 示例2:替换操作(将“张三”替换为“张叁”) ' destinationSheet.UsedRange.Replace What:="张三", Replacement:="张叁", LookAt:=xlPart ' 保存新工作簿 Dim newFilePath As String newFilePath = "C:\Path\To\NewWorkbook.xlsx" newWorkbook.SaveAs newFilePath ' 关闭新工作簿 newWorkbook.Close SaveChanges:=True ' 清理 Set dict = Nothing Set sourceSheet = Nothing Set destinationSheet = Nothing Set newWorkbook = Nothing For i = 1 To 3 Set sourceWorkbooks(i) = Nothing Next i MsgBox "处理完成!" End Sub ``` 注意: 1. 文件路径需要根据实际情况修改,或者使用文件选择对话框让用户选择。 2. 人名所在的列和起始行可能需要调整(这里假设A列,第2行开始)。 3. 字典去重是区分大小写的,如果需要不区分大小写,可以将姓名转换为统一的大小写(例如UCase或LCase)后再存入字典。 4. 其他数据处理部分(如筛选和替换)需要根据具体需求编写,示例中给出了两个常见的操作,但被注释掉了。 用户可以根据实际需求调整上述代码。如果三个工作簿已经打开,则不需要打开和关闭操作,可以直接使用Workbooks集合引用它们。 另外,如果用户需要更详细的格式设置(如边框、背景色等),可以在写入数据后添加相应的格式化代码。 如果需要使用文件选择对话框来选择三个源工作簿,可以使用以下函数: ```vb Function GetFilePath() As String Dim fd As FileDialog Set fd = Application.FileDialog(msoFileDialogFilePicker) fd.AllowMultiSelect = False fd.Title = "请选择工作簿" If fd.Show = -1 Then GetFilePath = fd.SelectedItems(1) Else GetFilePath = "" End If End Function ``` 然后在主程序中替换路径设置部分: ```vb For i = 1 To 3 sourceWorkbookPaths(i) = GetFilePath() If sourceWorkbookPaths(i) = "" Then MsgBox "用户取消了选择" Exit Sub End If Next i ``` 这样用户就可以依次选择三个工作簿。 请根据实际情况调整代码。 </think> 以下是使用VB宏语言实现从三个自定义工作簿提取人名、去重创建新工作簿并完成数据处理的全套解决方案: ```vb Sub ProcessDataFromWorkbooks() ' 骤1:定义变量 Dim sourceWBs(1 To 3) As Workbook Dim newWB As Workbook Dim srcSheet As Worksheet, destSheet As Worksheet Dim dict As Object Dim cell As Range Dim personName As String Dim i As Integer, lastRow As Long Dim sourceFiles As Variant ' 骤2:选择三个源文件 With Application.FileDialog(msoFileDialogFilePicker) .AllowMultiSelect = True .Title = "选择三个源工作簿" .Filters.Add "Excel Files", "*.xlsx;*.xls" If .Show <> -1 Then Exit Sub sourceFiles = .SelectedItems End With If UBound(sourceFiles) < 2 Then MsgBox "请选择至少三个工作簿!", vbExclamation Exit Sub End If ' 骤3:打开源工作簿并提取数据 Set dict = CreateObject("Scripting.Dictionary") For i = LBound(sourceFiles) To UBound(sourceFiles) Set sourceWBs(i) = Workbooks.Open(sourceFiles(i)) Set srcSheet = sourceWBs(i).Sheets("明细表") ' 假设工作表名为"明细表" ' 查找包含人名的列(这里假设在A列) lastRow = srcSheet.Cells(srcSheet.Rows.Count, "A").End(xlUp).Row ' 提取非空人名并去重 For Each cell In srcSheet.Range("A2:A" & lastRow) If Not IsEmpty(cell) Then personName = Trim(cell.Value) If personName <> "" Then dict(personName) = 1 ' 使用字典自动去重 End If End If Next cell Next i ' 骤4:创建新工作簿 Set newWB = Workbooks.Add Set destSheet = newWB.Sheets(1) destSheet.Name = "人员汇总" ' 骤5:设置工作表格式 With destSheet ' 设置标题行 .Range("A1").Value = "序号" .Range("B1").Value = "姓名" .Range("C1").Value = "部门" .Range("D1").Value = "状态" ' 设置标题格式 With .Range("A1:D1") .Font.Bold = True .Interior.Color = RGB(200, 200, 200) .Borders.Weight = xlThin End With ' 写入去重后的人名 i = 2 For Each personName In dict.Keys .Cells(i, 1).Value = i - 1 ' 序号 .Cells(i, 2).Value = personName ' 姓名 i = i + 1 Next ' 自动调整列宽 .Columns("A:D").AutoFit ' 添加边框 .Range("A1:D" & dict.Count + 1).Borders.Weight = xlThin End With ' 骤6:数据处理(示例:筛选和替换) With destSheet ' 替换特定内容(示例:将"离职"替换为"在职") .Columns("D:D").Replace What:="离职", Replacement:="在职", LookAt:=xlPart ' 设置筛选器 .Range("A1:D1").AutoFilter ' 示例筛选逻辑:仅显示特定部门 ' .Range("A1:D1").AutoFilter Field:=3, Criteria1:="技术部" End With ' 骤7:保存新工作簿 Dim savePath As String savePath = Application.GetSaveAsFilename( _ FileFilter:="Excel Files (*.xlsx), *.xlsx", _ Title:="保存汇总结果") If savePath <> "False" Then newWB.SaveAs savePath MsgBox "数据处理完成,结果已保存!", vbInformation End If ' 骤8:清理和关闭 For i = LBound(sourceFiles) To UBound(sourceFiles) sourceWBs(i).Close False Next i Set dict = Nothing Application.DisplayAlerts = True End Sub ``` ### 主要功能说明: 1. **数据提取** - 使用文件对话框选择三个源工作簿 - 从每个工作簿的"明细表"中提取A列数据(可修改列) - 使用字典对象自动去重 2. **新工作簿创建** - 自动创建新工作簿和工作表 - 预设标题行(序号、姓名、部门、状态) 3. **格式化设置** - 标题行加粗和背景色 - 自动调整列宽 - 添加单元格边框 - 设置筛选器 4. **数据处理** - 示例替换操作(离职→在职) - 支持按部门筛选(示例代码) 5. **输出保存** - 弹出保存对话框 - 保存为Excel文件 ### 使用骤: 1. 按`Alt+F11`打开VBA编辑器 2. 插入新模块并粘贴代码 3. 按`F5`运行宏 4. 选择三个源工作簿 5. 指定结果保存路径 ### 自定义修改点: 1. 修改列位置:将代码中的`"A"`替换为人名实际所在列 2. 更改工作表名:替换`"明细表"`为实际工作表名 3. 添加数据处理逻辑:在骤6区域扩展筛选/替换规则 4. 增加输出字段:在标题行添加新列并填充数据 > 提示:首次使用前需启用宏功能(文件→选项→信任中心→宏设置→启用所有宏)[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值