创建function时出错

本文解析了MySQL在开启bin-log时创建函数遇到的特定错误,并提供了两种解决方案:一是临时更改log_bin_trust_function_creators变量;二是永久设置该变量并在my.cnf配置文件中保存。

创建function时

出错信息:

ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

 

原因:

这是我们开启了bin-log, 我们就必须指定我们的函数是否是
1 DETERMINISTIC 不确定的
2 NO SQL 没有SQl语句,当然也不会修改数据
3 READS SQL DATA 只是读取数据,当然也不会修改数据
4 MODIFIES SQL DATA 要修改数据
5 CONTAINS SQL 包含了SQL语句

其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。如果我们开启了 bin-log, 我们就必须为我们的function指定一个参数。

解决方法:

SQL code

mysql>show variables like '%func%';

+---------------------------------+-------+

|Variable_name                  |Value|

+---------------------------------+-------+

|log_bin_trust_function_creators|OFF  |

+---------------------------------+-------+

1 row in set  (0.00sec)

mysql>set global log_bin_trust_function_creators=1;

Query OK,rows affected (0.00sec)

mysql>show variables like '%func%';

+---------------------------------+-------+

|Variable_name                  |Value|

+---------------------------------+-------+

|log_bin_trust_function_creators|ON   |

+---------------------------------+-------+

row in set (0.00sec)

mysql>

 

 

 

 

或者 

 

这样添加了参数以后,如果mysqld重启,那个参数又会消失,因此记得在my.cnf配置文件中添加:
log_bin_trust_function_creators=1

<think>这个错误通常发生在尝试设置数据透视表字段的Function属性,但该字段可能不适合作为数据字段(例如文本字段被设置为数据字段)。在我们的场景中,我们设置的是“数量”字段,它应该是数值类型。但如果“数量”列中存在非数值数据,或者该列被识别为文本,就会导致此错误。 解决方案: 1. 确保“HistoryStorage”工作表中的“数量”列(C列)包含的是数值数据,没有文本或空值(空值可以视为0)。 2. 在创建数据透视表之前,将“数量”列的数据类型明确设置为数值格式。 我们将修代码,在创建数据透视表之前先检查并确保“数量”列的数据类型正确。 修后的`CreateHistoryChart`过程(关键修部分): ```vba ' ... [前面的代码不变] ... ' 在创建数据透视表之前,确保数量列是数值类型 With wsHistory ' 将数量列转换为数字(如果可能) lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row For i = 2 To lastRow If IsNumeric(.Cells(i, "C").Value) Then .Cells(i, "C").Value = Val(.Cells(i, "C").Value) Else .Cells(i, "C").Value = 0 ' 非数字则设为0 End If Next i End With ' ... [创建数据透视表缓存和范围不变] ... ' 创建数据透视表 Set pivotTable = pivotTableCache.CreatePivotTable( _ TableDestination:=wsDashboard.Range("A5"), _ TableName:="HistoryPivot") ' 配置数据透视表字段 With pivotTable .PivotFields("记录日期").Orientation = xlRowField .PivotFields("记录日期").Position = 1 .PivotFields("模块名称").Orientation = xlColumnField .PivotFields("模块名称").Position = 1 ' 添加数据字段 Dim dataField As PivotField Set dataField = .AddDataField(.PivotFields("数量"), "数量", xlSum) dataField.NumberFormat = "0" ' 设置日期格式 .PivotFields("记录日期").NumberFormat = "yyyy-mm-dd" ' 设置紧凑布局 .RowAxisLayout xlTabularRow End With ' ... [后面的代码不变] ... ``` ### 修说明: 1. **数据类型转换**: ```vba For i = 2 To lastRow If IsNumeric(.Cells(i, "C").Value) Then .Cells(i, "C").Value = Val(.Cells(i, "C").Value) Else .Cells(i, "C").Value = 0 ' 非数字则设为0 End If Next i ``` - 遍历“数量”列(C列)的每一行 - 使用`IsNumeric`检查是否为数值 - 使用`Val`函数将字符串转换为数值(如果该单元格是文本格式的数字) - 非数值数据替换为0 2. **添加数据字段的替代方法**: ```vba Set dataField = .AddDataField(.PivotFields("数量"), "数量", xlSum) dataField.NumberFormat = "0" ``` - 使用`AddDataField`方法显式添加数据字段并指定汇总方式(求和) - 避免直接设置`Function`属性,使用此方法更可靠 ### 完整修后的`CreateHistoryChart`过程: 注意:为了清晰,我只展示修部分,其余部分保持不变。 ### 其他可能的问题及解决方案: 1. **字段名称错误**: - 确保HistoryStorage表的列标题为:A列“记录日期”,B列“模块名称”,C列“数量” - 如果列标题不一致,请修代码中的字段名称 2. **日期列包含非日期值**: - 同样在日期列进行数据清洗: ```vba ' 在创建数据透视表前,确保日期列有效 For i = 2 To lastRow If Not IsDate(wsHistory.Cells(i, "A").Value) Then wsHistory.Cells(i, "A").Value = Date ' 设为当前日期 End If Next i ``` 3. **数据透视表名称冲突**: - 确保每次创建数据透视表使用唯一的名称(如添加间戳): ```vba Set pivotTable = pivotTableCache.CreatePivotTable( _ TableDestination:=wsDashboard.Range("A5"), _ TableName:="HistoryPivot_" & Format(Now, "yyyymmddhhnnss")) ``` ### 错误处理增强: 在原始代码中已有错误处理,但可以添加更具体的错误信息: ```vba ErrorHandler: Application.ScreenUpdating = True MsgBox "创建图表出错: " & Err.Description & vbCrLf & _ "错误发生在: " & Erl, vbCritical ``` 注意:`Erl`需要配合行号使用,可以在关键代码行添加行号标记(如 `10: ...`)。 §§相关问题§§: 1. 在VBA中如何批量转换数据类型 2. Excel数据透视表常见错误及解决方法 3. 如何使用VBA创建动态图表 4. 在Excel中如何设计仪表盘(Dashboard)</think>### 解决"不能设置类PivotField的Function属性"错误 这个错误通常发生在尝试直接设置数据透视表字段的`Function`属性,但该属性在VBA中不可直接设置。以下是修复后的完整代码: ```vba Sub CreateHistoryChart() Dim wsHistory As Worksheet Dim wsDashboard As Worksheet Dim pivotTableCache As PivotCache Dim pivotTable As PivotTable Dim chartObj As ChartObject Dim slicerCache As SlicerCache Dim lastRow As Long Dim pivotRange As Range Dim dataField As PivotField On Error GoTo ErrorHandler Application.ScreenUpdating = False ' 检查HistoryStorage表是否存在 If Not WorksheetExists("HistoryStorage") Then MsgBox "HistoryStorage表不存在,请先运行记录历史功能", vbExclamation Exit Sub End If Set wsHistory = ThisWorkbook.Sheets("HistoryStorage") ' 创建仪表板工作表 If WorksheetExists("Dashboard") Then Application.DisplayAlerts = False ThisWorkbook.Sheets("Dashboard").Delete Application.DisplayAlerts = True End If Set wsDashboard = ThisWorkbook.Sheets.Add(After:=wsHistory) wsDashboard.Name = "Dashboard" ' 设置仪表板布局 With wsDashboard .Range("A1").Value = "历史数据趋势分析" .Range("A1").Font.Bold = True .Range("A1").Font.Size = 16 ' 添加说明文本 .Range("A3").Value = "使用以下切片器选择要显示的模块:" .Range("A3").Font.Bold = True End With ' 准备数据透视表范围 lastRow = wsHistory.Cells(wsHistory.Rows.Count, "A").End(xlUp).Row Set pivotRange = wsHistory.Range("A1:C" & lastRow) ' 创建数据透视表缓存 Set pivotTableCache = ThisWorkbook.PivotCaches.Create( _ SourceType:=xlDatabase, _ SourceData:=pivotRange) ' 创建数据透视表 Set pivotTable = pivotTableCache.CreatePivotTable( _ TableDestination:=wsDashboard.Range("A5"), _ TableName:="HistoryPivot") ' 配置数据透视表字段 - 修复部分 With pivotTable ' 添加行字段 .AddFields RowFields:="记录日期", ColumnFields:="模块名称" ' 添加数据字段 - 正确设置Function的方式 Set dataField = .AddDataField(.PivotFields("数量"), "数量总和", xlSum) dataField.NumberFormat = "0" ' 设置日期格式 .PivotFields("记录日期").NumberFormat = "yyyy-mm-dd" ' 设置紧凑布局 .RowAxisLayout xlTabularRow End With ' 创建图表 Set chartObj = wsDashboard.ChartObjects.Add( _ Left:=wsDashboard.Range("E1").Left, _ Top:=wsDashboard.Range("A10").Top, _ Width:=500, _ Height:=300) With chartObj.Chart .SetSourceData Source:=pivotTable.TableRange1 .ChartType = xlLineMarkers .HasTitle = True .ChartTitle.Text = "模块数量历史趋势" ' 设置坐标轴 With .Axes(xlCategory) .CategoryType = xlTimeScale .TickLabelPosition = xlLow End With With .Axes(xlValue) .MinimumScale = 0 .HasTitle = True .AxisTitle.Text = "数量" End With ' 美化图表 .PlotArea.Format.Fill.ForeColor.RGB = RGB(255, 255, 255) .ChartArea.Format.Fill.ForeColor.RGB = RGB(240, 240, 240) .Legend.Position = xlBottom End With ' 创建切片器 Set slicerCache = ThisWorkbook.SlicerCaches.Add( _ Source:=pivotTable, _ SourceField:="模块名称") With slicerCache.Slicers.Add( _ SlicerDestination:=wsDashboard, _ Name:="ModuleSlicer", _ Caption:="选择模块", _ Top:=wsDashboard.Range("A4").Top, _ Left:=wsDashboard.Range("B3").Left, _ Width:=200, _ Height:=150) .Style = "SlicerStyleLight1" .NumberOfColumns = 2 End With ' 调整布局 With wsDashboard .Columns("A:A").AutoFit .Columns("B:B").ColumnWidth = 25 .Rows("1:1").RowHeight = 30 End With ' 添加刷新按钮 Dim btn As Button Set btn = wsDashboard.Buttons.Add( _ Left:=wsDashboard.Range("F3").Left, _ Top:=wsDashboard.Range("A4").Top, _ Width:=100, _ Height:=25) With btn .Caption = "刷新数据" .OnAction = "UpdateHistoryChart" .Name = "RefreshChartButton" End With Application.ScreenUpdating = True Exit Sub ErrorHandler: Application.ScreenUpdating = True MsgBox "创建图表出错: " & Err.Description & vbCrLf & _ "错误号: " & Err.Number, vbCritical End Sub ' ===== 更新图表过程 ===== Sub UpdateHistoryChart() Dim wsHistory As Worksheet Dim wsDashboard As Worksheet Dim pivotTable As PivotTable Dim lastRow As Long On Error GoTo ErrorHandler Application.ScreenUpdating = False ' 检查工作表是否存在 If Not WorksheetExists("HistoryStorage") Then MsgBox "HistoryStorage表不存在", vbExclamation Exit Sub End If If Not WorksheetExists("Dashboard") Then MsgBox "Dashboard表不存在", vbExclamation Exit Sub End If Set wsHistory = ThisWorkbook.Sheets("HistoryStorage") Set wsDashboard = ThisWorkbook.Sheets("Dashboard") ' 查找数据透视表 On Error Resume Next Set pivotTable = wsDashboard.PivotTables("HistoryPivot") On Error GoTo 0 If pivotTable Is Nothing Then MsgBox "未找到数据透视表", vbExclamation Exit Sub End If ' 更新数据源范围 lastRow = wsHistory.Cells(wsHistory.Rows.Count, "A").End(xlUp).Row pivotTable.ChangePivotCache ThisWorkbook.PivotCaches.Create( _ SourceType:=xlDatabase, _ SourceData:=wsHistory.Range("A1:C" & lastRow)) ' 刷新数据透视表 pivotTable.RefreshTable ' 更新图表数据源 For Each chartObj In wsDashboard.ChartObjects chartObj.Chart.SetSourceData Source:=pivotTable.TableRange1 Next chartObj Application.ScreenUpdating = True MsgBox "图表已更新", vbInformation Exit Sub ErrorHandler: Application.ScreenUpdating = True MsgBox "更新图表出错: " & Err.Description & vbCrLf & _ "错误号: " & Err.Number, vbCritical End Sub ' ===== 辅助函数 ===== Function WorksheetExists(sheetName As String) As Boolean Dim ws As Worksheet On Error Resume Next Set ws = ThisWorkbook.Sheets(sheetName) WorksheetExists = Not ws Is Nothing On Error GoTo 0 End Function ``` ### 关键修复点解释: 1. **正确设置数据透视表字段**: ```vba ' 修复前(错误方式): .PivotFields("数量").Orientation = xlDataField .PivotFields("数量").Function = xlSum ' 修复后(正确方式): Set dataField = .AddDataField(.PivotFields("数量"), "数量总和", xlSum) dataField.NumberFormat = "0" ``` - 使用`AddDataField`方法添加数据字段 - 直接在方法中指定汇总函数(`xlSum`) - 设置字段的格式属性而不是Function属性 2. **简化字段布局**: ```vba ' 使用AddFields方法一次性设置行和列字段 .AddFields RowFields:="记录日期", ColumnFields:="模块名称" ``` - 替代多个单独的字段设置 - 提高代码可读性和执行效率 3. **增强错误处理**: ```vba ErrorHandler: MsgBox "创建图表出错: " & Err.Description & vbCrLf & _ "错误号: " & Err.Number, vbCritical ``` - 显示错误号和描述 - 帮助定位具体问题 ### 常见错误原因及解决方案: 1. **数据类型不匹配**: - 确保"数量"列包含数值数据 - 添加数据验证: ```vba ' 在记录历史验证数据类型 If Not IsNumeric(quantity) Then quantity = 0 End If ``` 2. **字段名称不匹配**: - 检查HistoryStorage表的列标题: - A列应为"记录日期" - B列应为"模块名称" - C列应为"数量" - 修复列标题不一致问题 3. **空数据透视表**: - 添加数据存在性检查: ```vba ' 检查是否有足够的数据 If lastRow < 2 Then MsgBox "没有足够的数据创建图表", vbExclamation Exit Sub End If ``` 4. **Excel版本兼容性问题**: - 添加版本检查: ```vba ' 检查Excel版本 If Val(Application.Version) < 15 Then ' Excel 2013+ MsgBox "此功能需要Excel 2013或更高版本", vbExclamation Exit Sub End If ``` ### 替代解决方案:使用传统方法 如果仍然遇到问题,可以使用更传统的方法创建数据透视表: ```vba ' 传统方法创建数据透视表 With pivotTable ' 添加行字段 With .PivotFields("记录日期") .Orientation = xlRowField .Position = 1 End With ' 添加列字段 With .PivotFields("模块名称") .Orientation = xlColumnField .Position = 1 End With ' 添加数据字段 - 传统方式 With .PivotFields("数量") .Orientation = xlDataField .Function = xlSum ' 这里可能在某些版本中仍然出错 .NumberFormat = "0" .Name = "数量总和" End With End With ``` ### 最佳实践建议: 1. **数据清洗**: ```vba ' 在创建图表前清洗数据 Sub CleanHistoryData() Dim ws As Worksheet Set ws = ThisWorkbook.Sheets("HistoryStorage") Dim lastRow As Long lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row For i = 2 To lastRow ' 确保数量是数值 If Not IsNumeric(ws.Cells(i, "C").Value) Then ws.Cells(i, "C").Value = 0 End If ' 确保日期有效 If Not IsDate(ws.Cells(i, "A").Value) Then ws.Cells(i, "A").Value = Date End If Next i End Sub ``` 2. **分步调试**: ```vba ' 在关键步骤添加调试信息 Debug.Print "创建数据透视表前,行数: " & lastRow Debug.Print "数据范围: " & pivotRange.Address ``` 3. **使用显式引用**: ```vba ' 明确指定工作表和工作簿 Set pivotTableCache = ThisWorkbook.PivotCaches.Create( _ SourceType:=xlDatabase, _ SourceData:="HistoryStorage!" & pivotRange.Address) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值