相信有些人会遇到过,想要用单元格进度条表示进度,但因为进度条的值只能是单元格的值,而不是从单元格的时间到今天时间的值。
本文章使用比较耗费算力的方法实现进度条。且每过一天就需要重新运算一下,以刷新新的一天显示进度。
主要实现方式是通过JS宏设定进度条(数据条)的最小值和最大值。
最小值为0,单元格值为20,最大值为100,那数据条就占单元格的五分之一
而我们在想要不改变单元格的值的情况下让进度条向前移动,就把最小值设定为-10,最大值设定为90,这样进度条就向前移动了。
比如:
最小值为:单元格日期-(今天日期-单元格日期)
最大值为:最大日期-(今天日期-单元格日期)
通过将进度条的轴整体向前移动(单元格日期->今天日期)实现,只要整体坐标向左移动,那就代表进度条向右移动了。
其实想要通过公式设定最小值最大值,但数据条只能绝对引用,没法完全下拉复用,如果进度条单元格比较少,还是可以实现的。那就只能通过JS宏实现,增加了难度。
实现代码
function demo(){
let endDate = new Date("2025/9/5")
let R = "A1" // 显示数据条的日期格式单元格
添加数据条(Range(R), RGB(0,255,255), new Date(Range(R).Text), endDate)
}
数据条相关模块
/** 以 日期格式 条件格式设置数据条 本单元格值->今天时间->结束时间值
* @param {Range} 单元格 日期格式
* @param {number |undefined} 条色 数据条颜色
* @param {number |undefined} 小值 数据的开始值 本单元格数值
* @param {number |undefined} 大值 数据的终点值
*/
function 添加数据条(格, 条色, 小值, 大值) {
let dataBar;
let tday = 取无时间今天();
if (判断有无数据条(格)) { // 已经有数据条 设定颜色
for (let c = 1; c <= 格.FormatConditions.Count; c++) { // 遍历 单元格式
let dygs = 格.FormatConditions.Item(c);
if (dygs.Type == xlDatabar) dataBar = dygs; // 找到数据条
}
} else { // 没有数据条 添加数据条 并添加颜色
dataBar = 格.FormatConditions.AddDatabar() // 添加数据条
dataBar.BarFillType = 0;//0=纯色
}
if (typeof 条色 !== 'undefined') {
dataBar.BarColor.Color = 条色
}
if (typeof 小值 !== 'undefined' && typeof 大值 !== 'undefined') {
let 前减偏差 = 时转日戳(tday) - 时转日戳(小值); //获得两个时间偏差
// |开始时间(单元格时间)|----|今天时间|----|终点时间|
// |开始时间-(今天时间-开始时间)|----|开始时间(单元格时间)|----|终点时间-(今天时间-开始时间)|
dataBar.MinPoint.Modify(xlConditionValueNumber, 时转日戳(小值) - 前减偏差) // 设置0位点 基准数值
dataBar.MaxPoint.Modify(xlConditionValueNumber, 时转日戳(大值) - 前减偏差) // 设置100位点 基准数值
}
}
/**判断单元格有无数据条 */
function 判断有无数据条(格) {
if (格.FormatConditions.Count > 0) { // 该单元格有 单元格式
for (let c = 1; c <= 格.FormatConditions.Count; c++) { // 遍历 单元格式
let dygs = 格.FormatConditions.Item(c);
if (dygs.Type == xlDatabar) return true // 如果找到就返回 true
}
}
return false // 默认没有
}
/** 删除单元格格式 数据条 其他单元格格式不受影响
* @param {Range} 格 单元格
*/
function 删除数据条(格) {
if (格.FormatConditions.Count > 0) { // 该单元格有 单元格式
for (let c = 1; c <= 格.FormatConditions.Count; c++) { // 遍历 单元格式
let dygs = 格.FormatConditions.Item(c);
if (dygs.Type == xlDatabar) dygs.Delete(); // 删除 数据条 单元格式
}
}
}
时间相关模块
/** 获取一个只有日期的今天日期对象
* @returns {Date} 没有时分秒毫秒的日期对象
*/
function 取无时间今天() {
let tday = new Date(); // 获取当前时间
tday.setHours(0, 0, 0, 0); // 当前时间清零
return tday;
}
/** 时间戳或者日期转日期戳
* @param {Number | Date} date 时间戳数值记得清除时分秒 或 日期对象
* @returns {Number} 日期戳数值 非日期或者数值返回 -1
*/
function 时转日戳(date) {
const startt = 25569; // 1900/1/1~1970/1/1=25568+1=25569
if (typeof date == 'number') {
return startt + Math.ceil(date / (24 * 60 * 60 * 1000))
} else if (isDate(date)) {
return startt + Math.ceil(date.getTime() / (24 * 60 * 60 * 1000))
} else {
return -1;
}
}
/** 是否是日期格式
* @param {object} obj 用于判断的对象
* @returns {boolean} 是日期对象返回true
*/
function isDate(obj) {return obj instanceof Date;}
#JS宏 #数据条 #条件格式 #进度条 #WPS
2991






