如何通过在线表格实现资源预定

【Excel VBA入门】还在为如何预定会议室而发愁吗?手把手教你开发一款实用小工具(二) ​源代码文件也已经上传, 附对应的资源文件连接:Excel VBA编程会议室预定 ​ 阅读详情

在日常的工作和生活中,我们常常需要预定会议室或者某个场所进行某个活动,例如:在公司里,需要预定某个时间段的会议室,还有在学校里,我们需要预定羽毛球馆、篮球馆、等等活动,像这种资源预定的场景比比皆是,那我们怎么能简单的实现资源预定呢?答案是通过zOffice在线表格

zOffice简介

zOffice提供云端Office能力,包括word、excel、ppt三类办公文档的在线协同编辑,通过专业级的文档能力,高效的协作体验,内容级的安全管控,丰富的集成开发接口,来赋能企业的业务系统,帮助业务系统实现文档在线预览和编辑,文档操作过程全部线上进行,完成在线办公的场景闭环。

zOffice链接:https://www.filez.com/zoffice

集成介绍文档:http:// https://lenovocloud.zbox.filez.com/l/a0OsO0

实现方案

1、方式一:通过zOffice多人协同在线编辑实现资源预定

业务系统可以与zOffice集成,具体如何集成参考:

https://hello.word.com/(替换成集成链接)

比如会议室预定,我们建一个这样的在线表格,只要想订会议室的人都可以进这个表格,也许你会认为别人会篡改你的内容,但是zOffice在线编辑有单元格历史记录,还有协作记录,如果你的内容被改了,很快就能找到是谁,非常的安全好用。

2、方式二:通过zOffice SDK实现

通过zOffice SDK实现资源预定,zOffice SDK拥有非常丰富的接口,可以通过监听预定的区域,当有人输入内容时,校验是否有冲突,冲突的结果可以用颜色标记。

步骤一:挂载一个会议室模板文件,定义一个app变量,添加监听

app.addListener('Workbook.Event.Change', callback);

当你输入内容,callback函数就会执行。

步骤二:获取会议室模板文件的会议室,预定日期

const roomsheet = await app.ActiveWorkbook.getSheetByName('会议室预定');

const meetingRoomNum: number[] = [702, 708, 709, 710];

const listendRange = roomsheet.getRange(1, 1, 30, 25);

const firstCol = roomsheet.getRange(1, 1, 30, 1); // 第一列存储了会议室

const firstRow = roomsheet.getRange(1, 1, 1, 25); // 第一行存储了预定日期

步骤三:判断输入的预定时间是否冲突,1代表冲突,0代表不冲突,可以设置条件格式用红色表示1。

所有的demo的代码如下:

      {

        text: '会议室demo',

        exec: async(app: Excel.APP) => {

          if (app.events.includes('Workbook.Event.Change')) {

            app.removeListener('Workbook.Event.Change');

            console.log('取消监听Change');

            return;

          }

          const callback = async(range: Excel.Range) => {

            console.log('会议室callback执行');

            if (isInsectedRange(listendRange, range)) { // 修改位置位于监听区域内

              const timeTableMap = await updateModel(); // update model

                // 获得冲突位置对应的item

                for (let i = 0; i < timeTableMap.length; i += 1) {

                  const currentRange = timeTableMap[i].timeRange;

                  if (isInsectedRange(currentRange, range)) { // 是冲突区间

                    const repeatTime = getRepeatTime(timeTableMap[i].timeArr);

                    const posRange = timeTableMap[i].posRange;

                    const ret = [];

                    for (let j = 0; j < repeatTime.length; j += 1) {

                      if (repeatTime[j]) {

                        ret.push(['1']);

                      } else {

                        ret.push(['0']);

                      }

                    }

                    await posRange.setValues(ret);

                  }

                }

            }

          };

          app.addListener('Workbook.Event.Change', callback);

          console.log('添加监听Change');

          const roomsheet = await app.ActiveWorkbook.getSheetByName('会议室预定');

          const meetingRoomNum: number[] = [702, 708, 709, 710];

          const listendRange = roomsheet.getRange(1, 1, 30, 25);

          const firstCol = roomsheet.getRange(1, 1, 30, 1); // 第一列存储了会议室

          const firstRow = roomsheet.getRange(1, 1, 1, 25); // 第一行存储了预定日期

          interface timeTableItem {

            room: number; // 房间号

            date: string; // 日期

            timeArr: string [][]; // 二维数组,n x 2 eg.start_time end_time

            timeRange: Excel.Range; // 用来存储timeArr所在的位置

            posRange: Excel.Range; // 用来存储冲突校验的结果

          }

          enum FindingType {

            FindDate = 1,

            FindRoom = 2,

            // FindCondition = 3,

          }

          const getIndexTable = async(targetRange: Excel.Range, type: FindingType): Promise<any> => {

            const mergedRanges = await targetRange.getMergedRanges();

            if (mergedRanges.length > 0) {

              switch (type) {

                case FindingType.FindDate: {

                  const ret: number[][] = [];

                  for (let i = 0; i < mergedRanges.length; i += 1) {

                    const current = mergedRanges[i];

                    if (current.endColumn > current.column) { // colspan > 1 认为是date

                      ret.push([current.column, current.endColumn]);

                    }

                  }

                  return ret;

                }

                case FindingType.FindRoom: {

                  const ret: number[][] = [];

                  for (let i = 0; i < mergedRanges.length; i += 1) {

                    const current = mergedRanges[i];

                    if (current.endRow > current.row) { // rowspan > 1 认为是room

                      ret.push([current.row, current.endRow]);

                    }

                  }

                  return ret;

                }

              }

            }

          };

          const rowIdx = await getIndexTable(firstCol, FindingType.FindRoom);

          const colIdx = await getIndexTable(firstRow, FindingType.FindDate);

          // 首先填充数据模型

          const updateModel = async() => {

            const timeTableMap: timeTableItem[] = [];

            for (let i = 0; i < rowIdx.length; i += 1) {

              for (let j = 0; j < colIdx.length; j += 1) {

                const roomCell = await firstCol.getCell(rowIdx[i][0], 1);

                const roomValue = await roomCell.getValue(); // 拿到房间号

                const dateCell = await firstRow.getCell(1, colIdx[j][0]);

                const dateValue = await dateCell.getValue(); // 拿到日期

                const timeRange = await roomsheet.getRange(rowIdx[i][0], colIdx[j][0], rowIdx[i][1], colIdx[j][1]); // 拿到时间数组所在的位置

                const timeValues = await timeRange.getValues(); // 拿到时间数组

                // 拿到条件格式位置信息(没有时间内容,不算posRange

                const timeLen = timeValues.length;

                const posRange = await roomsheet.getRange(rowIdx[i][0], colIdx[j][1] + 1, rowIdx[i][0] + timeLen - 1, colIdx[j][1] + 1);

                timeTableMap.push({ room: roomValue, date: dateValue, timeArr: timeValues, posRange, timeRange });

              }

            }

            return timeTableMap;

          };

          // 寻找冲突项

          const isInsectedRange = (targetRange: Excel.Range, sourceRange: Excel.Range) => {

            const rowInsected = !(targetRange.endRow < sourceRange.row  targetRange.row > sourceRange.endRow);

            const colInseted = !(targetRange.endColumn < sourceRange.column  targetRange.column > sourceRange.endColumn);

            return rowInsected && colInseted ? true : false;

          };

          // 其次判断时间冲突

          const getRepeatTime = (timeArr: string[][]) => {

            const len = timeArr.length;

            const repeatFlag: boolean[] = Array(len).fill(false);

            for (let i = 0; i < timeArr.length; i += 1) {

              const orderA = timeArr[i];

              if (!isValidTimeArr(orderA)) {

                repeatFlag[i] = true;

                if (isEmptyArray(orderA)) repeatFlag[i] = false;

                continue;

              }

              for (let j = i + 1; j < timeArr.length; j += 1) {

                const orderB = timeArr[j];

                if (!isValidTimeArr(orderB)) {

                  repeatFlag[j] = true;

                  if (isEmptyArray(orderB)) repeatFlag[i] = false;

                  continue;

                }

                if (!(orderA[1] <= orderB[0]  orderA[0] >= orderB[1])) {

                  repeatFlag[i] = true;

                  repeatFlag[j] = true;

                }

              }

            }

            return repeatFlag;

          };

          // 是否是合法的时间组

          const isValidTimeArr = (timeArr: string[]) => {

            const startTime = timeArr[0];

            const endTime = timeArr[1];

            // eslint-disable-next-line eqeqeq

            if (startTime === ''  startTime == null  endTime === ''  endTime == null) { // 缺少开始时间或者结束时间,false

              return false;

            }

            if (startTime > endTime) { // 开始时间大于结束时间,false

              return false;

            }

            return true;

          }

          // 是否为空数组

          const isEmptyArray = (arr: string[]) => {

            if (arr.length > 0) {

              return false;

            }

            return true;

          };

        },

      },

    ],

  },

总结

综上,可以通过集成zOffice在线编辑和zOffice SDK两种方式简单快捷的实现资源预定。

【Excel VBA入门】还在为如何预定会议室而发愁吗?手把手教你开发一款实用小工具(一) 本期给大家介绍的是一款Excel 和VBA编写的会议室预定小工具,编码的每个细节和源码都毫无保留的分享给大家,供大家学习使用 阅读详情

相关推荐

基于Java+Jsp+Servlet+Mysql实现的酒店预定管理系统设计与实现

一款由jsp+servlet+mysql实现的酒店管理系统,后台没有用到框架,用的是基础的servlet,前端用了一个仿win10的界面模板和layui前端框架,界面非常漂亮大气。主要实现的功能有:管理员登录、楼层管理、房型管理、房间管理、预定管理、入住管理、查看账单、日志管理、用户管理等,所有管理列表页面都提供了导出到excel的功能。此外还可以设置系统背景壁纸,非常方便

jinku7662_的博客 1303

记一次失败的使用EXCEL实现资源预约系统的尝试

起因 大概是我这有个会议室,然后很多人要使用,那就要大家登记一下,而且登记的时候能检查时间是否冲突就最好了。看了一下也没有现成的东西可以用,后来就想到了在线文档,如果做个共享表格来登记的话就行了。 需求 能写时间,这个很容易 能判断冲突,这个逻辑很简单,但是在Excel里面就没那么容易了 实现 现在在线文档有几家在做,随便打开了腾讯的,然后进去新建一个表格。大概看了一下面板,有数据验证,可以下拉选项,这个用来做第一点需求。然后还有挺多函数可以用,想了一下开始动手尝试。 先大概这样建个表头。 然后要让人

qi_w_ip的博客 1914

EXCEL+VBA实现会议安排

应朋友工作要求,利用EXCEL+VBA制作出会议安排。根据会议需要,选择出总表中相应几个部门的所有人员组成新的表格,如果总表中人员有更新,可以点击按钮对所有已生成表格进行更新。

开源城市运动预约的工具类小程序源码

开源城市运动预约的工具类小程序源码

软希网分享源码的博客 1018

会议室预约系统

主要面向初学者的一些基本的内容,有助于大家对会议室系统的了解

会议室预定管理系统

本系统为B/S架构应用程序 主要包含以下功能:会议室预订、报表汇出、批量预订、历史数据删除、会议室设定、用户管理、密码修改、密码重置 会议室预订: 显示公司每一个会议室一周的预订信息,预订人员可以根据会议室预订状况,合理安排 会议时间 报表汇出 : 根据会议室预订现状汇出Excel报表 会议室设定: 管理维护会议室信息 用户管理 : 维护本系统用户信息。本系统用户分为 管理员和普通用户 密码修改 : 用户通过此功能修改自己的密码 密码重置 : 管理员可重置其他用户的密码。重置后密码默认为:111111,本系统初始用户为admin V2.1版本新增功能 : 批量预订 : 长时间批量预订,选取日期起讫,勾选星期,选取时间段,即可批量预订 历史数据删除 : 对于已经过期的会议预订,可进行删除,仅保留最新一个月的预订资料

【Java毕设项目】基于SpringBoot的民宿在线预定平台

目前,界面设计已经成为对软件质量进行评价的一条关键指标,一个好的用户界面可以使用户使用系统的信心和兴趣增加,从而使工作效率提高,JSP技术是将JAVA语言作为脚本语言的,JSP网页给整个服务器端的JAVA库单元提供了一个接口用来服务HTTP的应用程序。一旦输入系统的数据不正确,那么处理后的输出就会扩大这些错误,因此输入的数据的准确性对整个系统的性能起着决定性意义。输出是由电脑对输入的基本信息进行解决,生成高质量的有效信息,并使之具有一定的格式,提供给管理者使用,这是输出设计的主要责任和目标。

葫芦娃的博客 624

边缘AI硬件风向:从专用芯片到端侧大模型

边缘AI硬件正呈现五大发展趋势:专用AI加速芯片(如华为昇腾、谷歌EdgeTPU)凭借高能效比成为主流;端侧大模型催生支持Transformer架构的新硬件需求;存算一体技术突破内存墙限制;FPGA和可重构计算提供灵活性;异构集成与Chiplet技术实现模块化设计。这些发展需要配套软件工具链支持,未来边缘设备将演变成具备本地智能的"智能体",竞争焦点转向算力、能效、易用性和成本的多维平衡。

qq_37027335的博客 348

springboot基于JAVA的民族婚纱预定系统的设计与实现论文

现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本民族婚纱预定系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此民族婚纱预定系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线选择试题并完成答题,在线查看考核分数。

QQ1694456187的博客 963

Qt快速读取Excel文件

网上很多读取方式都是如下形式,太慢了,打开文件+读取文件要6s以上,实在是受不了! QAxObject excel("Excel.Application"); excel.setProperty("Visible", false); QAxObject *work_books = excel.querySubObject("WorkBooks"); work_boo...

c+c++的博客 2万+

KUKA-外部自动运行模板程序——个人设计模式&思路

用于说明KUKA与西门子PLC外部自动交互模板的设计思路与使用流程

qq_39024187的博客 5612

基于Springboot民宿在线预订系统【附源码+文档】

该课题采用的主流的Java语言这种面向对象的语言进行民宿在线预订系统程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。

程序定制,毕设辅导、论文写作、技术指导! 2121

DCDC开关节点SW的Layout抉择:打孔换层与EMI共模辐射的权衡

本文深入探讨了DCDC转换器中开关节点SW的Layout设计对EMI共模辐射的影响。通过分析SW节点的EMI辐射机制、打孔换层对输入环路的影响以及铜皮面积与共模辐射的量化关系,提出了工程实践中的权衡策略和优化方法,帮助工程师在设计中平衡EMI性能和电路效率。

weixin_29722783的博客 246

基于Spring Boot的企业会议室预定管理系统

基于Spring Boot的企业会议室预定管理系统通过信息化手段,解决了传统会议室管理中的痛点,为企业提供了高效、准确、安全的会议室管理解决方案。系统不仅适用于企业行政部门,还可与员工、部门经理等角色协作,共同完成会议室管理任务。未来,随着技术的不断进步,系统可进一步集成AI智能调度、语音预定等功能,为企业提供更智能、更全面的会议室管理支持。文章底部可以获取博主的联系方式,获取源码、查看详细的视频演示,或者了解其他版本的信息。所有项目都经过了严格的测试和完善。

QQ1694456187的博客 819

Pulpino SoC中挂载AXI从机接口的自定义IP说明

AXI 从机接口挂载 Pulpino SoC 调试Pulpino SoC中挂载AXI从机接口的自定义IP说明PULPion SoC介绍自定义AXI IP挂载IP挂载框图代码修改脚本修改自定义AXI IP调试C语言编写软件调试硬件调试 Pulpino SoC中挂载AXI从机接口的自定义IP说明 本篇文章主要从工程的角度描述了如何将具有AXI从机接口的自定义IP挂载到Pulpino SoC上,其中不涉及到SoC中的任何原理知识。 PULPion SoC介绍 PULPion SoC整体架构如下图所示, PULPi

小陈的芯片学习之路 2211

深入理解EtherCAT状态机:从IGH代码看伺服电机如何从‘上电’到‘使能’

本文深入解析EtherCAT状态机的工作原理,重点探讨伺服电机从'上电'到'使能'的状态转换过程。通过分析状态字(Status Word)和控制字(Control Word)的交互机制,结合IGH代码实例,揭示DS402状态机的核心逻辑,帮助工程师解决60%以上的伺服控制问题,提升EtherCAT网络调试效率。

weixin_42549037的博客 289

【超全】基于SSM的主题酒店预定系统[包括源码+文档]

该课题采用的主流的Java语言这种面向对象的语言进行场主题酒店预订系统程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。

qq_59110836的博客 1011

借助Claude实现Playwright的自动化(MCP Server)

MCP Server自己开发也是可以的,现在也有很多开箱即用的MCP Server,可以在https://github.com/modelcontextprotocol/servers中查找。

Criss@陈磊 4228

基于Java+SSM+Mysql实现的在线挂号预约管理系统设计与实现

基于Spring+SpringMVC+Mybatis框架,这个系统很值得大家去学习,因为这个后端页面也很不错、里面的代码质量也可以,自己可以加更多的功能做毕设非常完美,如果购买后想加功能可以联系我哦,可以给一些指导,这里的功能如果一比一的做出来的话提升一定很大,很有进步,实战才是展现技术的最佳表现。 系统主要有以下功能:系统管理、医院管理、医生管理、病人管理、科室管理、挂号管理、新闻管理。 前端使用的是Easyui框架 简单方便,很容易学习而且有中文文档哦。

jinku7662_的博客 1048

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

java毕业设计基于SpringBoot企业会议室预定管理系统

企业会议室预定管理系统基于Spring Boot框架开发,采用前后端分离架构,后端使用Spring Security保障安全性,前端采用Vue.js/React构建交互界面。系统核心功能包括会议室管理、在线预定、冲突检测、审批流程、使用统计等模块,实现了会议室资源的数字化管理。通过WebSocket实时更新会议室状态,支持移动端访问,具有高效性、准确性和安全性等特点。系统采用MySQL存储数据,Redis缓存高频访问数据,可与企业OA系统集成,有效解决传统会议室管理的痛点问题。文末提供源码获取方式,支持毕设

qq_1406299528的博客 886

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

2025毕设ssm体育场馆预定网站程序+论文

另外,不同的场馆类型众多,包括羽毛球馆、篮球馆、游泳馆等,各自有着不同的运营模式和需求,这也增加了场馆预定管理的复杂性。用户可以随时随地通过网络查看各个场馆的详细信息,如场馆位置、设施设备、开放时间、价格等,然后根据自己的需求快速预定场馆,无需再像传统方式那样逐个打电话或亲自前往场馆咨询预定。[2] 刘小玲, 李慧云, 殷珊珊, 贾少华, 许杰辉, 郝颖. 一种基于软件测试任务的信息化管理系统的原型设计[J]. 现代信息科技, 2024, 8 (12): 91-95。

卢卡毕设程序 1309

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

SSM场地预定平台55nqh《开发全资源(程序 / 源码 / 数据库)+ 万言论文(文末)+ 系统界面》

本文开发基于 SSM 框架的场地预定平台,分析用户与管理员需求,设计并实现线上预约、场地管理等功能,解决传统预定问题,提升场地使用与管理效率,为场地预定提供便捷解决方案。

W321468的博客 946

基于SpringBoot的民宿预定管理系统设计与实现

文章摘要 随着旅游业的快速发展,民宿行业市场规模持续扩大,预计2025年将突破2000亿美元。然而,传统管理方式难以应对订单处理、房源管理的复杂性,存在信息不对称、预订流程繁琐等问题。基于SpringBoot框架的民宿预定管理系统应运而生,整合MyBatis、Vue.js等技术,提供房源管理、订单处理、财务对账等功能,解决行业痛点。该系统面向中小民宿业主,具备LBS智能推荐、多维度数据分析等特色功能,支持无接触服务需求。技术选型成熟,采用微服务架构,确保系统稳定性和可扩展性。项目具有显著市场必要性和可行性,

xn19950718的博客 164

基于nodejs+vue车位预定管理系统[程序+论文+开题]-计算机毕业设计

本项目的研究意义在于通过构建车位预定管理系统,实现车位信息的实时更新与智能匹配,为用户提供便捷的车位查询与预定服务,减少因寻找车位而产生的无效行驶时间,降低碳排放,促进绿色出行。同时,系统还能帮助停车场管理者实现车位的有效调度与监控,提高停车场运营效率,减少人力成本,提升顾客满意度。此外,该系统的应用还将促进智慧城市的建设,为城市交通管理提供有力支持,推动城市交通系统的智能化、精细化发展。

星海学长_毕设 1181
上一篇: 利用zOffice SDK实现合同续签系统
下一篇: 通过zOffice SDK实现灵活的数据统计
联想Filez协同办公
博客等级 码龄5年 6粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值