ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 313|回复: 9

[求助] 报价得分的计算

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-5-16 11:32 | 显示全部楼层 |阅读模式
  1. Sub CalculateBidScores()
  2.     Dim ws As Worksheet
  3.     Set ws = ThisWorkbook.Sheets("Sheet1") ' 请根据实际情况修改工作表名称
  4.    
  5.     Dim lastRow As Long
  6.     lastRow = ws.Cells(ws.Rows.count, "B").End(xlUp).Row ' 假设公司名在B列
  7.    
  8.     Dim A0 As Double
  9.     Dim S As Double
  10.     Dim M As Long
  11.     Dim downRate As Double
  12.     Dim basePrice As Double
  13.     Dim i As Long
  14.    
  15.     ' 假设下浮率已经在某个单元格中定义,例如D1
  16.     downRate = ws.Range("F12").Value
  17.    
  18.     ' 计算A0,这里需要所有合格投标人的评标价
  19.     ' 假设评标价在列C中,从第17行开始
  20.     A0 = Application.WorksheetFunction.Average(ws.Range("C17:C" & lastRow))
  21.    
  22.     ' 根据A0的值确定S
  23.     Select Case A0
  24.         Case Is < 100
  25.             S = 1
  26.         Case Is >= 100 And A0 < 1000
  27.             S = 5
  28.         Case Else
  29.             S = 10
  30.     End Select
  31.    
  32.     ' 计算基准价
  33.     basePrice = CalculateBasePrice(ws.Range("C17:C" & lastRow), S) * (1 - downRate)
  34.    
  35.     ' 循环每一行,计算价格得分
  36.     For i = 17 To lastRow
  37.         Dim bidPrice As Double
  38.         Dim score As Double
  39.         Dim n As Integer
  40.         
  41.         bidPrice = ws.Cells(i, "C").Value ' 假设报价在C列
  42.         
  43.         ' 根据评标价与基准价的比较确定n的值
  44.         If bidPrice > basePrice Then
  45.             n = 3 ' 正向系数
  46.         Else
  47.             n = 1 ' 负向系数
  48.         End If
  49.         
  50.         Debug.Print basePrice
  51.         
  52.         ' 计算价格得分
  53.         score = 40 - 40 * n * Abs(basePrice - bidPrice) / basePrice
  54.         If score < 0 Then score = 0 ' 如果得分小于0,则按0分计
  55.         
  56.         ' 在工作表中填入价格得分
  57.         ws.Cells(i, "F").Value = score ' 假设价格得分在F列
  58.     Next i
  59. End Sub

  60. Function CalculateBasePrice(rng As Range, S As Double) As Double
  61.    Dim cell As Range
  62.     Dim price As Double
  63.     Dim roundedPrice As Double
  64.     Dim lowestPrice As Double
  65.     Dim highestPrice As Double
  66.     Dim uniquePrices As Object
  67.     Set uniquePrices = New collection
  68.    
  69.    
  70. ' 填充Collection对象,保留每个四舍五入后的报价的最低值
  71.     For Each cell In rng
  72.         If Not IsEmpty(cell.Value) Then
  73.             price = Round(cell.Value / S, 0) * S ' 四舍五入到S的倍数
  74.             If Not uniquePrices.Exists(price) Then ' 检查Collection中是否已存在该价格
  75.                 uniquePrices.Add price
  76.             Else
  77.                 ' 如果已经存在相同四舍五入后的报价,则更新为最低报价
  78.                 Dim existingPrice As Variant
  79.                 For Each existingPrice In uniquePrices
  80.                     If price < existingPrice Then
  81.                         ' 移除原有的报价并添加新的更低报价
  82.                         uniquePrices.Remove existingPrice
  83.                         uniquePrices.Add price
  84.                         Exit For
  85.                     End If
  86.                 Next existingPrice
  87.             End If
  88.         End If
  89.     Next cell
  90.    
  91. <font color="#ff0000">    ' 将Collection转换为数组
  92.     Dim pricesArray() As Double
  93.     j = 1
  94.     For Each price In uniquePrices
  95.         pricesArray(j) = price
  96.         j = j + 1
  97.     Next price</font>
  98.    
  99.     Dim M As Long
  100.     M = uniquePrices.count
  101.    
  102.     ' 根据M的值去除最高价和最低价
  103.     If M >= 7 Then
  104.         highestPrice = Application.WorksheetFunction.Large(uniquePrices, 1)
  105.         uniquePrices.Remove (highestPrice)
  106.         lowestPrice = Application.WorksheetFunction.Small(uniquePrices, 1)
  107.         uniquePrices.Remove (lowestPrice)
  108.     ElseIf M = 6 Then
  109.         highestPrice = Application.WorksheetFunction.Large(uniquePrices, 1)
  110.         uniquePrices.Remove (highestPrice)
  111.     End If

  112.    ' 计算基准价
  113.     If Not IsEmpty(prices) Then
  114.         CalculateBasePrice = Application.WorksheetFunction.Average(prices)
  115.     Else
  116.         CalculateBasePrice = 0 ' 如果没有报价,则返回0或适当的值
  117.     End If

  118. End Function

  119. ' 辅助函数,用于从数组中移除指定数量的异常值(最高或最低)
  120. Function RemoveOutliers(arr As Variant, ParamArray outliers() As Variant) As Variant
  121.     Dim result() As Variant
  122.     Dim i As Long, j As Long
  123.     Dim outlierCount As Long
  124.     outlierCount = 0
  125.     For Each v In outliers
  126.         outlierCount = outlierCount + 1
  127.     Next v
  128.    
  129.     ReDim result(LBound(arr) To UBound(arr) - outlierCount)
  130.     j = 0
  131.     For i = LBound(arr) To UBound(arr)
  132.         Dim isOutlier As Boolean
  133.         isOutlier = False
  134.         For Each outlier In outliers
  135.             If arr(i) = outlier Then
  136.                 isOutlier = True
  137.                 Exit For
  138.             End If
  139.         Next outlier
  140.         
  141.         If Not isOutlier Then
  142.             j = j + 1
  143.             result(j) = arr(i)
  144.         End If
  145.     Next i
  146.    
  147.     RemoveOutliers = result
  148. End Function
复制代码
上述代码想要实现逻辑:通过投标报价计算出报价得分,首先筛选有效报价:1、算出算数平均值,依据平均值大小确定S值。2、每个报价除以S并四舍五入,在进行比较,若值相等则取报价中的最小值作为有效报价,不相等则正常取值,并且统计有效报价的数量作为M。3、依据M值确定是否去除最高或者最低价,然后进行基准值计算,最终再依据公式得出报价得分。但是在实际编写中标红段一直有问题,且基准值basePrice一直获取不到。能否请各位大神帮忙看看这里面的问题。感谢!

报价得分计算.zip

16.42 KB, 下载次数: 10

TA的精华主题

TA的得分主题

发表于 2024-5-16 11:48 | 显示全部楼层
你上传的文件好像没有任何代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-5-16 12:18 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
fanyoulin 发表于 2024-5-16 11:48
你上传的文件好像没有任何代码

我的代码直接贴出来了,wps的宏好像没保存上

TA的精华主题

TA的得分主题

发表于 2024-5-16 12:46 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
投标人名称一栏不能为空,空的话造成取到的行号错误:
image.png

TA的精华主题

TA的得分主题

发表于 2024-5-16 12:50 | 显示全部楼层
后面还存在多处错误,我改了一下,请看附件测试。(计算逻辑没动,也没看是否对)

工作簿2.zip

28.27 KB, 下载次数: 13

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-5-16 13:46 | 显示全部楼层
longwin 发表于 2024-5-16 12:46
投标人名称一栏不能为空,空的话造成取到的行号错误:

投标人我这是有的,没放出来,啊哈哈

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-5-16 13:47 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
longwin 发表于 2024-5-16 12:50
后面还存在多处错误,我改了一下,请看附件测试。(计算逻辑没动,也没看是否对)

哇,感谢,我去试试

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-5-16 14:18 | 显示全部楼层
longwin 发表于 2024-5-16 12:50
后面还存在多处错误,我改了一下,请看附件测试。(计算逻辑没动,也没看是否对)

再次感谢大佬,就是在计算过程中double属性计算结果会产生较大的误差,有没有什么方法能解决精度丢失的问题啊

TA的精华主题

TA的得分主题

发表于 2024-5-16 14:36 | 显示全部楼层
wbksy 发表于 2024-5-16 14:18
再次感谢大佬,就是在计算过程中double属性计算结果会产生较大的误差,有没有什么方法能解决精度丢失的问 ...

请看下面链接资料,用cDec()的方法试试
https://blog.csdn.net/weixin_39986896/article/details/111212325

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-5-17 09:11 | 显示全部楼层
longwin 发表于 2024-5-16 14:36
请看下面链接资料,用cDec()的方法试试
https://blog.csdn.net/weixin_39986896/article/details/111212 ...

感谢,搞出来了。非常感谢大佬!
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-17 11:48 , Processed in 0.045937 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表