一、概况

随着人工智能(AI)技术快速发展,工程测量领域正经历从传统测绘向智能测量的跨越式转型。当前施工企业在复杂地形测绘、动态监测、数据建模等环节仍面临效率不足、精度受限等挑战,AI工具的深度学习与智能分析能力为突破行业瓶颈提供了新路径。DeepSeek作为国内领先的AI技术服务商,其智能化模型在实时数据处理、多维度场景预测及高精度决策支持方面具备显著优势,可深度赋能工程测量全流程的智能化升级‌。比如:通过AI算法实时处理激光雷达、无人机航测等多源数据,自动生成高精度三维地形模型,相较传统测绘效率提升。

对于施工测量人员来说,可通过DeepSeek 多模态AI技术融合实现对数据的实时处理,显著提升其工作效能。本文基于Excel VBA开发自定义函数,集成DeepSeek API实现参数智能解析与多源数据协同处理‌。

二、DeepSeek介绍

DeepSeek是一家专注通用人工智能(AGI)的中国科技公司,主攻大模型研发与应用。DeepSeek-R1是其开源的推理模型,擅长数学、代码和自然语言推理‌,性能比肩 OpenAI o1正式版。DeepSeek-V3擅长高效文本处理、代码生成及多模态任务,支持长上下文‌。DeepSeek的技术优势是基于大模型实现海量数据的实时分析,向用户提供智能对话、文本生成、语义理解、计算推理等应用。

三、开发自定义函数

Excel VBA自定义函数开发流程可分为六个步骤,各环节需遵循以下技术要求:

‌1.启用开发工具‌

通过文件→选项→自定义功能区激活开发工具选项卡‌,该模块包含VBA编辑器入口及宏安全设置功能。

‌2.创建代码模块‌

在VBA编辑器中右键点击工程资源管理器,选择插入→标准模块‌,命名自定义函数。

‌3.编写函数结构‌

采用Function/End Function语法框架声明函数‌,编写函数代码。

注:点击工具→引用DLL动态链接库“Microsoft Scripting Runtime”

4‌.设置参数验证‌

通过函数校验输入数据类型‌,添加异常捕获模块,实现错误处理机制。

‌5.集成API调用‌

注册云服务平台获取API密钥,在函数模块顶部声明API连接对象‌,实现函数与DeepSeek大模型连接。

6‌.应用自定义函数

将自定义函数的工作簿另存为XLSM格式,在工作表单元格中输入函数名,单元格作为参数传递给函数实现与DeepSeek大模型交互。

注:WPS用户需要额外安装WPS VBA支持库。

四、自定义函数源码

Dim BASE_URL As String
Dim API_KEY As String
Dim API_MODEL As String

‘ 添加单元格处理相关常量
Private Const CELL_PLACEHOLDER As String = “□” ‘ 空单元格占位符
Private Const CELL_SEPARATOR As String = ” | ” ‘ 单元格分隔符
Private Const ROW_SEPARATOR As String = vbNewLine ‘ 行分隔符

‘部分源码来源:bilibili UP主

Function Chat_Function(userContent As String, Optional systemMessage As String = “你是一个乐于助人的AI助手,请根据用户的问题给出详细的解答。”) As String ‘对话函数
Dim httpRequest As Object
Dim requestBody As String
Dim responseText As String
Dim csp As String
On Error GoTo ErrorHandler
Application.Calculation = xlManual ‘关闭自动重算

csp = “硅基流动” ‘云服务商(必填),以硅基流动为例
BASE_URL = “https://api.siliconflow.cn/v1/chat/completions” ‘base_url(必填)
API_KEY = “请输入你在硅基流动申请的API密钥” ‘api_key(必填)
API_MODEL = “Pro/deepseek-ai/DeepSeek-V3” ‘模型名model(必填)

‘ 创建HTTP对象(兼容64位Excel)
Set httpRequest = CreateObject(“MSXML2.XMLHTTP.6.0”)

If csp = “火山引擎” Then

‘ 构建符合火山引擎要求的请求体
requestBody = “{ ” & _
“””model””: “”” & API_MODEL & “””, ” & _
“””messages””: [” & _
“{“”role””: “”system””, “”content””: “”” & json_Encode(systemMessage) & “””},” & _
“{“”role””: “”user””, “”content””: “”” & json_Encode(userContent) & “””}” & _
“]” & _
“}”

ElseIf csp = “DeepSeek” Then

‘ 构建符合DeepSeek要求的请求体
requestBody = “{ ” & _
“””model””: “”” & API_MODEL & “””, ” & _
“””messages””: [” & _
“{“”role””: “”system””, “”content””: “”” & systemMessage & “””},” & _
“{“”role””: “”user””, “”content””: “”” & json_Encode(userContent) & “””}” & _
“], ” & _
“””stream””: false” & _
“}”

ElseIf csp = “硅基流动” Then

‘ 构建符合硅基流动要求的请求体
requestBody = “{ ” & _
“””model””: “”” & API_MODEL & “””, ” & _
“””messages””: [” & _
“{“”role””: “”system””, “”content””: “”” & systemMessage & “””},” & _
“{“”role””: “”user””, “”content””: “”” & json_Encode(userContent) & “””}” & _
“], ” & _
“””temperature””: 0″ & _
“}”

End If

‘ 发送API请求
With httpRequest
.Open “POST”, BASE_URL, False
.setRequestHeader “Content-Type”, “application/json”
.setRequestHeader “Authorization”, “Bearer ” & API_KEY
.send requestBody
End With

‘ 处理响应
If httpRequest.status = 200 Then
responseText = httpRequest.responseText

‘ 使用正则表达式提取内容
Dim regEx As Object
Set regEx = CreateObject(“VBScript.RegExp”)
regEx.Global = True
regEx.Pattern = “””content””\s*:\s*””((?:\\””|[^””])*)”””

Dim matches As Object
Set matches = regEx.Execute(responseText)

If matches.Count > 0 Then
Chat_Function = DecodeJSON(matches(0).SubMatches(0))
Else
Chat_Function = “错误:未找到有效响应内容”
End If
Else
Chat_Function = GetStatusError(httpRequest.status, httpRequest.statusText)
End If

Application.Calculation = xlAutomatic ‘开启自动计算
Set httpRequest = Nothing

Exit Function

ErrorHandler:
Chat_Function = “运行时错误:” & Err.Description
Set httpRequest = Nothing

End Function

‘ JSON转义处理
Private Function EscapeJSON(ByVal text As String) As String
Dim result As String
result = Replace(text, “\”, “\\”)
result = Replace(result, “”””, “\”””)
result = Replace(result, vbCr, “\r”)
result = Replace(result, vbLf, “\n”)
result = Replace(result, vbTab, “\t”)
result = Replace(result, vbBack, “\b”)
result = Replace(result, Chr(12), “\f”)
EscapeJSON = result
End Function

‘ JSON解码处理
Private Function DecodeJSON(ByVal text As String) As String
DecodeJSON = text
DecodeJSON = Replace(DecodeJSON, “\”””, “”””)
DecodeJSON = Replace(DecodeJSON, “\\”, “\”)
DecodeJSON = Replace(DecodeJSON, “\r”, vbCr)
DecodeJSON = Replace(DecodeJSON, “\n”, vbLf)
DecodeJSON = Replace(DecodeJSON, “\t”, vbTab)
DecodeJSON = Replace(DecodeJSON, “\b”, vbBack)
DecodeJSON = Replace(DecodeJSON, “\f”, Chr(12))
‘处理特殊字符
DecodeJSON = Replace(DecodeJSON, “\u003e”, “>”)
DecodeJSON = Replace(DecodeJSON, “\u003c”, “<“)
DecodeJSON = Replace(DecodeJSON, “\u003d”, “=”)
DecodeJSON = Replace(DecodeJSON, “\u0022”, “”””)
DecodeJSON = Replace(DecodeJSON, “\u0027”, “‘”)
DecodeJSON = Replace(DecodeJSON, “\u005c”, “\”)
DecodeJSON = Replace(DecodeJSON, “\u0026”, “&”)
End Function

‘ 状态码错误处理
Private Function GetStatusError(status As Long, statusText As String) As String
Select Case status
Case 400: GetStatusError = “请求参数错误(400)”
Case 401: GetStatusError = “认证失败,请检查API密钥(401)”
Case 403: GetStatusError = “权限不足(403)”
Case 429: GetStatusError = “请求过于频繁,请稍后重试(429)”
Case 500: GetStatusError = “服务器内部错误(500)”
Case 503: GetStatusError = “服务不可用(503)”
Case Else: GetStatusError = “API错误 [” & status & “] ” & statusText
End Select
End Function

‘ 处理单元格引用的函数
Private Function fw(prompt As String) As String
Dim result As String
result = prompt

‘ 正则表达式模式匹配单元格引用
Dim regEx As Object
Set regEx = CreateObject(“VBScript.RegExp”)

‘ 匹配模式:单元格引用(如A1, B2:C3等)
regEx.Pattern = “([A-Za-z]+[0-9]+)(:[A-Za-z]+[0-9]+)?”
regEx.Global = True

Dim matches As Object
Set matches = regEx.Execute(prompt)

‘ 处理每个匹配的单元格引用
Dim match As Object
For Each match In matches
Dim cellRef As String
cellRef = match.Value

‘ 获取单元格值
Dim cellValue As String
On Error Resume Next

If InStr(cellRef, “:”) > 0 Then
‘ 处理单元格范围
cellValue = qy(range(cellRef))
Else
‘ 处理单个单元格
cellValue = d_dyg(range(cellRef))
End If
On Error GoTo 0

‘ 替换提示中的单元格引用为实际值
result = Replace(result, cellRef, cellValue)
Next match

fw = result
End Function

‘ 获取单元格范围的值的函数
Private Function qy(rng As range) As String
If rng Is Nothing Then
qy = “无效区域引用”
Exit Function
End If

Dim result As String
Dim cell As range
Dim currentRow As Long
Dim isFirstCell As Boolean

‘ 添加区域标识,去掉$符号
Dim rangeAddr As String
rangeAddr = Replace(rng.Address(False, False), “$”, “”)
result = rangeAddr & “区域数据:” & ROW_SEPARATOR

‘ 添加列标题(如果范围超过1列)
If rng.Columns.Count > 1 Then
isFirstCell = True
Dim col As range
For Each col In rng.Columns
If Not isFirstCell Then
result = result & CELL_SEPARATOR
End If
result = result & Replace(Split(col.Cells(1).Address, “$”)(1), “$”, “”)
isFirstCell = False
Next col
result = result & ROW_SEPARATOR
End If

‘ 初始化行追踪
currentRow = rng.Row
isFirstCell = True

‘ 处理每个单元格
For Each cell In rng.Cells
‘ 检查是否需要换行
If cell.Row > currentRow Then
result = result & ROW_SEPARATOR
currentRow = cell.Row
isFirstCell = True
End If

‘ 添加分隔符
If Not isFirstCell Then
result = result & CELL_SEPARATOR
End If

‘ 添加单元格值
result = result & IIf(Len(cell.text) = 0, CELL_PLACEHOLDER, cell.text)
isFirstCell = False
Next cell

qy = result
End Function

‘ 处理单个单元格内容的函数
Private Function d_dyg(cell As range) As String
If cell Is Nothing Then
d_dyg = “无效单元格引用”
Exit Function
End If

‘ 获取单元格的实际值,去掉$符号
Dim cellAddr As String
cellAddr = Replace(cell.Address(False, False), “$”, “”)

d_dyg = cellAddr & “的值为” & _
IIf(Len(cell.text) = 0, CELL_PLACEHOLDER, cell.text)
End Function

‘选区:选择工作表某个区域返回的字符串
Function xuanqu(rng As range) As String
Dim result_a As String
Dim result_b As String
Dim cell As range
Dim currentRow As Long
Dim isFirstCell As Boolean

If rng Is Nothing Then
xuanqu = “无效区域引用”
Exit Function
End If

‘ 添加区域标识,去掉$符号
Dim rangeAddr As String
rangeAddr = Replace(rng.Address(False, False), “$”, “”)
result_a = rangeAddr & “区域数据:” & ROW_SEPARATOR

‘ 添加列标题(如果范围超过1列)
If rng.Columns.Count > 1 Then
isFirstCell = True
Dim col As range
For Each col In rng.Columns
If Not isFirstCell Then
result_a = result_a & CELL_SEPARATOR
End If
result_a = result_a & Replace(Split(col.Cells(1).Address, “$”)(1), “$”, “”)
isFirstCell = False
Next col
result_a = result_a & ROW_SEPARATOR
End If

‘ 初始化行追踪
currentRow = rng.Row
isFirstCell = True

‘ 处理每个单元格
For Each cell In rng.Cells
‘ 检查是否需要换行
If cell.Row > currentRow Then
result_a = result_a & ROW_SEPARATOR
currentRow = cell.Row
isFirstCell = True
End If

‘ 添加分隔符
If Not isFirstCell Then
result_a = result_a & CELL_SEPARATOR
End If

‘ 添加单元格值
result_a = result_a & IIf(Len(cell.text) = 0, CELL_PLACEHOLDER, cell.text)
isFirstCell = False
Next cell

result_b = result_a

‘ 正则表达式模式匹配单元格引用
Dim regEx As Object
Set regEx = CreateObject(“VBScript.RegExp”)

‘ 匹配模式:单元格引用(如A1, B2:C3等)
regEx.Pattern = “([A-Za-z]+[0-9]+)(:[A-Za-z]+[0-9]+)?”
regEx.Global = True

Dim matches As Object
Set matches = regEx.Execute(prompt)

‘ 处理每个匹配的单元格引用
Dim match As Object
For Each match In matches
Dim cellRef As String
cellRef = match.Value

‘ 获取单元格值
Dim cellValue As String
On Error Resume Next

If InStr(cellRef, “:”) > 0 Then
‘ 处理单元格范围
cellValue = qy(range(cellRef))
Else
‘ 处理单个单元格
cellValue = d_dyg(range(cellRef))
End If
On Error GoTo 0

‘ 替换提示中的单元格引用为实际值
result_b = Replace(result_b, cellRef, cellValue)
Next match

xuanqu = result_b
End Function

注:以上函数需要引用解析JSON数据的工具模块‌JsonConverter.bas

JsonConverter.bas下载地址:https://github.com/VBA-tools/VBA-JSON/blob/master

五、自定义函数说明

函数名称:

=Chat_Function(“请输入你的问题”,”系统角色”)

函数用法:

=Chat_Function(“请用新年快乐写一首诗。”)

=Chat_Function(“人工智能对我们未来的学习、生活和工作都将产生哪些影响?”,”你是个乐于助人的助手。”)

=Chat_Function(“【任务】:对产品分类。【要求】:只返回“物体、饮料、水果”中的一个。【产品】:”&A9)

=Chat_Function(“【任务】:”&xuanqu(A19:B30)&”计算选中区域销售额的平均值。”,B5)

函数参数说明:

第1参数:用户问题(必需)

第2参数:系统角色(可选,默认助手角色)

角色分为“‌通用助手角色、领域专家角色、交互增强角色、数据处理角色、多模态支持角色”等。

选择区域需套用xuanqu函数,如:xuanqu(A7)或xuanqu(A1:A7)

注:文本需要使用英文””引号和&合并连接符号。

系统角色(可选文字):

你是人工智能助手

你是一个Excel公式专家。用户会描述他们需要的功能,你只需要直接返回对应的Excel公式,不需要任何解释。确保返回的是可以直接在Excel中使用的完整公式。

六、自定义函数应用

实例1:计算两点方位角和距离

示例:

在B8单元格输入:=Chat_Function(“【要求】:计算测站点”&xuanqu(B4:B5)&”至放样点”&xuanqu(B6:B7)&”两点的直线方位角。【要求】:计算正确,直接返回结果,格式为°′″,不需要解释。”)

在B9单元格输入:=Chat_Function(“【要求】:计算测站点”&xuanqu(B4:B5)&”至放样点”&xuanqu(B6:B7)&”两点的水平距离。【要求】:计算正确,直接返回结果,单位添加m,保留3位数,不需要解释。”)

结果:

注:经验算,计算结果正确。

实例2:格式转换

示例:

在B14单元格输入:=Chat_Function(“【问题】:”&B13&”。【任务】:问题中的格式为六十进制,需要转换成十进制。【要求】:直接返回结果,不需要解释。”)

结果:

注:经验算,计算结果正确。

实例3:编写测量方案

示例:

在B19单元格输入:=Chat_Function(“【问题】:”&B18&”。【要求】:适用于公路工程,字数1000~1500。”)

结果:

实例4:名词解释

示例:

在B24单元格输入:=Chat_Function(“【问题】:”&B23&”。【要求】:引用“测绘基本术语”,不需要过度解释。”)

结果:

实例5:查找曲线要素

示例:

在B29单元格输入:=Chat_Function(“【问题】:”&B28&”。【要求】:通用于铁路、公路工程,不需要过度说明。”)

结果:

实例6:查找软件

示例:

在B34单元格输入:=Chat_Function(“【问题】:”&B33&”。【要求】:通用于GNSS静态测量基线解算,列出软件名称,不需要解释。”)

结果:

实例7:代码编写

示例:

在B39单元格输入:=Chat_Function(“【问题】:”&xuanqu(B38)&”。【任务】:适用于工程测量。【要求】:只返回代码,不需要说明。”,”你是Excel VBA专家”)

结果:

注:经验算,计算结果正确。

实例8:直线坐标计算程序

示例:

在B50单元格输入:=Chat_Function(“【问题】:”&xuanqu(A43:B49)&”。【任务】:根据问题中的“项目”条件设计一款直线坐标计算程序,调用“项目”对应的“数值”计算X坐标和Y坐标,计算条件是“计算桩号”对应的“数值”。【要求】:X坐标、Y坐标显示调换,只返回结果数字,不需要解释。”)

结果:

注:经验算,坐标X=0,坐标Y=10,计算结果正确。

实例9:文本润色

示例:

在B55单元格输入:=Chat_Function(“【原句】:”&B54&”。【要求】:原句润色,不需要解释。”)

结果:

七、下载地址

为避免繁琐操作流程,现已提供可直接下载的自定义函数表格文件,用户下载后可直接在Excel/WPS表格使用(WPS需要安装VBA支持库),无需重复编写代码,该表格包含预置函数代码及使用说明文档。

链接:https://pan.baidu.com/s/10E5QN3-BVsbnjMjs9TjvqA?pwd=fstp 提取码:fstp

重要提示:为确保自定义函数正常调用,请先配置API密钥。具体步骤:打开「模型设置」工作表,在E列单元格api_key栏填写从AI云服务平台获取的API密钥‌。未完成密钥配置前,自定义函数调用将返回「#VALUE!」错误提示‌。

八、结论

在Excel中实现AI深度赋能,除了使用自定义函数,还可以通过OfficeAI插件调用DeepSeek API完成表格智能分析‌。另外,在本地部署DeepSeek-R1大模型创建知识库,可以实现测量方案预审、规范检索、文档总结等智能服务,通过自然语言交互降低人工操作强度‌。

声明:本文系作者授权【学测量】发表,如需转载请注明出处。

本内容为作者个人观点,不代表学测量网站立场.
如对本文有异议或投诉,联系bd@xueceliang.cn

作者简介

评论

  1. ice

    哈哈,这些东西还是尽量拿来做文职工作吧,现在的大模型AI都存在自行虚构资料或参考依据的情况,但凡没有仔细检查,就直接使用原地爆炸了。
    在了解底层原理和逻辑的时候可以使用它来减轻压力,否则AI编码并不比人类更加高明,有时候它导致的错误更加隐蔽,因为人类有时候会在自己熟悉的领域下意识忽略一些“低级错误”,导致产生的错误不容易被排查。
    而且大部分ai编码训练的数据集都是老的C或者C++等项目,编码风格一言难尽,变量是26个字母+数字编号组合起来循环使用,看得人头大。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注