Access交流中心

北京 | 上海 | 天津 | 重庆 | 广州 | 深圳 | 珠海 | 汕头 | 佛山 | 中山 | 东莞 | 南京 | 苏州 | 无锡 | 常州 | 南通 | 扬州 | 徐州 | 杭州 | 温州 | 宁波 | 台州 | 福州 | 厦门 | 泉州 | 龙岩 | 合肥 | 芜湖 | 成都 | 遂宁 | 长沙 | 株洲 | 湘潭 | 武汉 | 南昌 | 济南 | 青岛 | 烟台 | 潍坊 | 淄博 | 济宁 | 太原 | 郑州 | 石家庄 | 保定 | 唐山 | 西安 | 大连 | 沈阳 | 长春 | 昆明 | 兰州 | 哈尔滨 | 佳木斯 | 南宁 | 桂林 | 海口 | 贵阳 | 西宁 | 乌鲁木齐 | 包头 |

一道较有挑战性的问题(已上传附件)

王剑辉  发表于:2011-09-21 12:32:16  
复制

A表中,有一字段“原始”,值如下:

 

参数1,参数2,参数3

3

x0,y0

x1,y1

x2,y3

线ID1,长度1

参数1,参数2,参数3

4

x4,y4

x5,y5

x6,y6

x7,y7

线ID2,长度2

参数1,参数2,参数3

2

x8,y8

x9,y9

线ID3,长度3

 

 

 

1、意思是:3为下边有3个节点坐标串,4为下边有4个节点坐标串,2为下面有2个坐标串;(注:本表所描述的实际意义是3根线,首先是它的各项参数,然后是每根线上有多少个节点,线上每个节点的坐标,该线的ID号及长度)

2、怎样通过SQL或者VBA实现,当:

删除了某些节点,如删除了x0,y0这个节点,则3要变成2;若我删除了x6,y6和x7,y7这两个节点,则4要变成2;

(不过,肯定不会把整根线所有节点都删除:)

 

 

请各位高手共同指教,谢谢。注意其中的规律是,除了线的节点数,其他所有行的值都有逗号。

 

点击下载此附件

 

Top
都市侠影 发表于:2011-09-21 16:43:20
没看到你的表的设计,不清楚情况。

煮江品茶 发表于:2011-09-21 17:18:16

1、建两个表:

线路表:线路ID(主键),线路名称,长度
线段表:线路ID(外键),线段ID(主键),X,Y,删除否(逻辑型)

 

2、写一个查询:

select 线路ID,线路名称,Dcount("*","线段表","线路ID=" & [线路ID] & " and 删除否=0") as 线段数
from 线路表



dbaseIIIer 发表于:2011-09-21 20:00:25

虽然你的架构设计很差, 不过代码不就是一行一行的编!

 

如果你是保存向量数据, 应该是先记录图形的 ObjectId, 再记录 Object 属性的.

编辑图形后, 也是整图保存的, 不会改一个 Object 就更新已保存的整图的.

 

而所有图形设计软件, 如 AutoCAD, CorelDraw, GerberEdit, 3DMax 等,

操作上都是先点选ObjectId, 显示了所有节点, 才移动或删除某一节点的.

 

设计上将会是  图形 Class 内的一个 DelPoint 的方法 去处理的.

 

你现在的设计, 最好操作反而是一个文本文件, 完全不觉得你这样保存数据有什么意义!

 

若果以你现在的设计真的编的话, 我们假设

1. 没逗号的数据就是一个新Object,

2. 设所有数据固定小数位长度为3

(不假设小数点的话,在有数据 3.273777 时会找不到 3.273 的点的)

(而大部份的正规绘图软件都是保存整数的, Access 的座标系统都是以 twips 为保存单位的)

3. 删除一个点, 必需确定ObjectId的, 在你的设计内,就以线Id 作为 ObjectId 吧!

(避免误删相同点座标的线)

 

 

 

Sub DelPoint( ObjectId as String, x, y)

Dim bmPoint as String

fmt="0.000"

Set rs = currentdb().openrecordset("A表")

rs.FindFirst "[原始] Like '" & ObjectId & ",*"   '注意数据保存 必需有个逗号结尾 不然会 Line12 会搜错 Line1 的

 

ToBeFound = Format(x, fmt) & "," & Format( y, fmt)

Done = False

rs.MovePrevious

Do while not rs.bof()

    If Instr( rs!原始, ",") = 0 Then Exit Do

    If rs!原始 = ToBeFound Then

       Done=True

       bmPoint = rs.bookmark

       Exit Do

    End If

    rs.MovePrevious

loop

If Not Done Then

    Msgbox "找不到该节点!"

Else

    Do While Not rs.bof()

        if Instr( rs!原始, ",") = 0 Then    '判断是否为线的第一行

             rs.Edit

             rs!原始 = val(rs!原始)-1       '进行修改, 不过注意, 若果只剩2个点以下的都不是线了 是否删除整物件自己处理

             rs.Update

             rs.bookmark = bmPoint

             rs.Delete

        End If

        rs.MovePrevious

    Loop

    If rs.bof() Then Msgbox "找不到物件的首行!"

End if

set rs=Nothing

 

End Sub



王剑辉 发表于:2011-09-21 20:34:53

楼上老师别生气,因为这个是MAPGIS明码格式,它就是这样的格式,OBJECTID就是放在最后面。

我只是通过DoCmd.TransferText acImportFixed, "Temp spec", "mks", "d:\1.txt", 0 导入进来,还没做任何编辑。

我发附件的时候,考虑到涉密,删除了一些东西,仅保留了实例的部分内容。



dbaseIIIer 发表于:2011-09-21 21:12:40

我就是知道原来是文本格式的文件,其实不用导进Access的,

就用代码处理 txt 文本还好!

 

接受上面的代码就结帖吧!

 

不然再编个直接修改 txt 文件的代码吧!



王剑辉 发表于:2011-09-21 22:29:44

老师能加一下我的qq:190325800吗?我传2个文件给您。再说一下要求。



王剑辉 发表于:2011-09-21 23:11:53

还望继续跟进帮忙,谢谢!

任务来源及txt格式附件:



王剑辉 发表于:2011-09-21 23:12:38
dbaseIIIer 发表于:2011-09-22 03:30:56

因为你读取的是 MAPGIS, 每个图数据量庞大, 而错误线少, 

所以我反过来编, 是

    循序读入 GIS 数据, 才检查是否要删除, 马上输出该线至 3.txt,

而不是

    读入错误Z线数据, 而每次搜寻GIS数据,更改,再保存.

 

Sub GGGG()


Dim Path, ObjId, x, y As String
Dim a As String, m, n As Long
Dim Lines As Long, nLine As Long
Dim InputPts As Long, OutputPts As Long, sx As String, sy As String
Dim ptXY(255)

On Error Resume Next
On Error GoTo 0
DoCmd.RunSQL "Drop table InvalidPt"

DoCmd.RunSQL "create table InvalidPt (objid text(3), x text(20), y text(20))"


Path = "D:\Backup\我的文档\AccessSoft\"

Open Path & "2.txt" For Input As #2
a = ""
Do While Not a Like "-----*"
    Line Input #2, a
Loop
Line Input #2, a
DoCmd.SetWarnings False
Do While Not a Like "-----*"
    ObjId = ParseN(a)
    ObjId = ParseN(a)
    x = ParseN(a)
    y = ParseN(a)
    DoCmd.RunSQL "Insert into InvalidPt values ('" & ObjId & "','" & x & "','" & y & "')"
   
    Line Input #2, a
Loop
DoCmd.SetWarnings True
Close #2

Open Path & "1.txt" For Input As #1
Open Path & "3.txt" For Output As #3

Line Input #1, a        '默认前两行为一样的输出
Print #3, a
Line Input #1, a        '第二行为线数
Lines = Val(a) - 1
Print #3, a


For nLine = 1 To Lines
    Line Input #1, a        '每条线的颜色,层次,宽度等参数, 不作修改直接保存
    Print #3, a
   
    Line Input #1, a        '读入点数
    InputPts = Val(a)
    OutputPts = InputPts
    For n = 1 To InputPts   '此循环读入所有点
        Line Input #1, ptXY(n)    ' 读入一点
    Next
    Line Input #1, a                'ObjId 行
    ObjId = Left(a, InStr(a, ",") - 1)


    For n = 1 To InputPts   '此循环检查每一点是否要删除
        m = InStr(ptXY(n), ",")
        sx = Left(ptXY(n), m - 1 - 1)   '错误节点是 5位小数的
        sy = Mid(ptXY(n), m + 1, Len(ptXY(n)) - m - 1) '错误节点是 5位小数的
        If Not IsNull(DLookup("[x]", "InvalidPt", "[ObjId]='" & ObjId & "' and [x]='" & sx & "' and [y]='" & sy & "'")) Then
            OutputPts = OutputPts - 1
            ptXY(n) = "X"
        End If
    Next


    Print #3, LTrim(Str(OutputPts))
    For n = 1 To InputPts           '此循环写入需要的点
        If ptXY(n) <> "X" Then Print #3, ptXY(n)
    Next
    Print #3, a                     '写入ObjId 行
Next

Close #3
Close #1

End Sub

 

Function ParseN(ByRef s As String)  '此函数用来截取 错误点上的每一个空格分隔值
    s = LTrim(s)
    sp = InStr(s, " ")
    If sp = 0 Then
        ParseN = s
        s = ""
    Else
        ParseN = Left(s, sp - 1)
        s = LTrim(Mid(s, sp))
    End If
End Function



王剑辉 发表于:2011-09-22 13:50:32

基本搞定,还差一步,在数据量大的时候,下标越界,我将Dim ptXY(255)改的足够大后,不提示下标越界。

但是执行完毕后,发现后面的点都没有被删除。

麻烦再调试一下,附件已上传,3个分卷。



王剑辉 发表于:2011-09-22 13:58:43
王剑辉 发表于:2011-09-22 20:02:07
已解决,是生成表的字段长度不够导致循环结束

总记录:12篇  页次:1/1 9 1 :