ARTICLE · 1199718
Excel 中使用一行公式把任务列表变成甘特图
做工程的人都知道
进度不能靠脑子记,一张会自己画进度条的表,比任何口头汇报都有说服力
我们前面用 Excel 做过一张工程量进度跟踪表——那是事后记录,活干到哪儿、填到哪。但项目一启动,更需要的是事前排期:谁、什么时间、干什么、干多久。这就是甘特图干的事。
一提甘特图,很多人第一反应是装 Project。但它太重、收费、团队里未必人人都有授权。其实你电脑里人人都有的Excel(或WPS),配合两个函数加一个条件格式,就能做出一张可以打印、可以每天自动刷新的甘特图。本文就带你从零做出来,所有公式可直接抄。
01
PART
思路:Excel 画甘特图
THINKING · 不画真正的图
先说清甘特图的本质:甘特图其实就是左边一列任务清单,右边一条时间轴,每个任务在时间轴上占一段横条。横条的位置=起止日期,横条的长度=工期。看一眼就知道任务是否有交叉、当前任务整体季度、哪天该交差。
这里使用 Excel 画甘特图的做法不是在 Excel 里画真正的图,而是在任务表右侧,拉出一排日期列(每列代表一周或一天)。然后用条件格式判断:这一格的日期,是不是落在某条任务的起止区间里?如果落在某条任务的起止区间里就填色,否则就留白。一连串被填色的格子拼起来,就是那条任务的横条——一张表格型甘特图。
这个方法有三个好处:① 数据还是那张任务表,改个日期,横条自动变长变短;② 零插件、零 VBA,任何版本 Excel/WPS 都能打开;③ 打印出来就是一张项目排期图,工作汇报、项目周会直接甩出,满满的成就感。

02
PART
基础:任务表+自动工期
BASE · 先把数据立住
先建一张任务表。将项目拆分为详细的活动,具体可根据你实际的项目情况进行增减,我这里任务表各列内容如下:
将你所有的任务以及任务排期填写到这张任务表中。

对于状态列,为了防止使用人员输入的格式不统一、造成无法统计,这里要统一设置为下拉选择的格式。具体的操作方法是:
①鼠标框选 E2 至 E21 列。

②将顶部菜单栏切换到数据菜单,选择下拉列表,在弹出的插入下拉列表中,选中“手动添加下拉项”,点击右侧加号,在下面分别输入 未开始、进行中 和 已完成,然后点击确认。

③确认后,在状态列点击,会有三角号显示,点击可以看到下拉项。

新建一个 sheet 表格,重命名为节假日,在里面输入在项目进度计划的区间中涉及的节假日日期。

关键来了:工期不要手动填,用NETWORKDAYS自动算。它和直接“结束减开始”的区别是——自动剔除周末和法定假日。语法很简单:
=NETWORKDAYS(C2,D2,节假日!A2:A19)
三个参数:起始日期、结束日期、节假日范围。第三个参数是精髓——选中上面新建的节假日表中的法定假日清单,NETWORKDAYS 就会把它们从工期内扣掉,国庆、春节不再虚增天数。

✦ 一个小提醒
C、D 两列务必用 Excel 的“日期”格式,不要手打“3月2日”。文本日期在后面所有公式里都会被当成“不是日期”,这样甘特条永远画不出来。
注:上面公式里的 节假日!A2:A19 是“节假日”表的日期范围,请按你实际建的表调整起止行号。
03
PART
核心:用条件格式画出甘特条
CORE · 全文最关键一步
拉出时间轴:在右侧建一排日期列
在任务表右侧(从 H 列开始),往后拉出一排时间轴。建议用周列:每列标题填一个周一的真实日期。列标题必须是真实日期,不要写“第1周”这种文本。这一行的日期,是后面公式判断的“坐标轴”。

选中甘特区域,新建“公式型”条件格式
选中任务一的甘特区域(如 H2:AO21,行是任务行、列是时间轴列)。

点“开始 → 条件格式 → 新建规则 → 使用公式确定要设置格式的单元格”。在公式框里输入下面这条:
=AND($E2="已完成", H$1>=$C2, H$1<=$D2)

然后再点击下面的“格式”按钮,在弹出的单元格格式中,选中图案卡片,选择绿色。

点击确认返回。

这条公式看着长,拆开就三层意思,全靠美元符号在管方向:
$E2 状态列
列绝对、行相对。锁住 E 列、行随任务变——同一行的状态固定,下拉到下一行自动看下一行的状态。
H$1 时间轴表头
行绝对、列相对。锁住第 1 行、列随格子横移——每列都看自己头顶的日期,横拉到下一列自动换日期。
$C2 / $D2 起止日期
都绝对列、相对行。锁住 C/D 两列,行随任务变。AND 三条件同时满足,说明“这一格的日期落在了这条任务的工期里”→ 填色。
为什么是“表头日期在起止之间”,而不是在任务行里找日期?因为条件格式是逐格判断的,每一格都必须能独立算出自已“该不该上色”。把坐标轴放在表头、把起止放在任务行,每个格子用自己的列头日期去比对这一行的起止,逻辑就自洽了。
点击确认,可以看到在 Excel 中,已经出现了进度条。

为了能区分每一行的进度条,选中整个活动区域,然后添加边框,这样看起来就更清晰了。

再建两条规则:进行中(黄)、未开始(灰)
同法新建两条,只把状态条件换掉,填充色分别选黄、灰。三条规则互不冲突,因为同一行只有一个状态:
=AND($E2="进行中", H$1>=$C2, H$1<=$D2)
=AND($E2="未开始", H$1>=$C2, H$1<=$D2)
!踩坑提示 🕳
最常见的两个翻车:一是把 $E2 写成 $E$2(锁死行),结果所有行都去看第 2 行的状态,整张图只有一条亮;二是列标题写成了“第1周”文本,公式里 H$1>=日期 永远不成立,条全白。两者都源于“引用方向”相反了。

04
PART
进阶:今天线 · 冻结窗格
PRO · 让它更好用
进度条画好了,再补两个让它“活”起来的细节。
加一条“今天”进度线
选中时间轴表头那一行(H1:AO1),新建公式条件格式。用 TODAY() 让表头里“包含今天的那一周”自动变蓝底——每天打开,蓝标自动跳到当前周:
=AND(H$1<=TODAY(), H$1+6>=TODAY())

这里 H$1 是某周一,加 6 是它所在的周日。命中“今天落在这一周”就填色。同理,你也可以在任务行里对“剩余工作日”用 NETWORKDAYS(TODAY(), 结束日期, 节假日) 自动算出还差几天。

冻结窗格,让图表跟着表走
甘特图往右拉几十列,滚动时左侧任务名就跑出屏幕了。将鼠标点击 G 列的任意一行,点“视图 → 冻结窗格 → 冻结至 E 列”,左侧任务清单固定,右侧时间轴滚动,对照看不串行。


到这一步,你已经有了一张会自己更新的甘特图:改状态,条换色;改日期,条伸缩;每天打开,今天线自动跳。再在顶部放几个公式(整体完成率、剩余天数),就是一张项目驾驶舱。
05
PART
避坑:5 个最常见翻车点
CHECK · 做完对照一遍
开始/结束写成文本。公式不认文本日期,工期和甘特条全失效——务必用日期格式。
时间轴列标题是“第1周”之类的文本而非真实日期。公式拿文本和日期比大小,永远不成立,条全白。
条件格式里引用方向写反:该相对的写成绝对($E$2)、该行本相对的写成锁死,导致所有行看同一行状态。
NETWORKDAYS 的节假日范围指向错误区域。引用写错行,国庆春节没被扣,工期凭空多几天。
条件格式“应用范围”没覆盖全部任务行。新增任务忘了扩范围,新行的条画不出来。
///
LAST
写在最后
你交付的是一套机制
你真正做出来的,不是一张图,而是一套会每天自己更新的排期机制。它和上一篇文章写的“工程量进度跟踪表”刚好前后呼应:计划表管“事前排期”,跟踪表管“事后记录”,项目从启动到收尾,两张表全覆盖。
一张表,让进度自己说话















































































