AutoCAD ObjectArx获取矩形信息输出到EXECL文档

一、需求

在Autocad绘制多个矩形,获取矩形的名称跟长宽并通过代码把这些信息输出到EXECL文件中

二、准备

下面的笔记中将会用到libxl第三方库来进行EXECL文件的创建,所以需要提前下好libxl

libxl下载地址:LibXL download

libxl的使用需要付费,但是我们只是学习所以下面将会演示破解的使用(支持正版)

三、开发

1.配置项目库引用

右击项目>>属性 

按照下图把libxl的相关目录引入进来

2.将libxl.dll丢进Autocad的安装目录,到这里libxl的配置就结束了

2.代码

添加类

代码如下:

Document.h:

#pragma once
class Document
{
public :
	static void InitApp();
	static void UnLoad();
public:
	static wchar_t* Name;
	static wchar_t* Key;
};

Document.cpp

#include "stdafx.h"
#include <dbmain.h>
#include <dbapserv.h>
#include <dbents.h>
#include <acdocman.h>
#include "libxl.h"
#include <sstream>
#include <iostream>
#include <string>
#include "Document.h"
#include "StdAfx.h"
#include <vector>
#include <fstream>


wchar_t* Document::Name = nullptr;
wchar_t* Document::Key = nullptr;

//定义一个矩形结构体
struct rectangle
{
	ACHAR* Name;
	double Length;
	double Width;
};
void GenerateExcelDocument(std::vector<rectangle> rectangles);
// 获取 AutoCAD 中所有图形的属性
void GetAllEntities()
{
	// 获取模型空间块表记录
	AcDbBlockTable *pBlockTable;
	acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead);

	AcDbBlockTableRecord *pModelSpace;
	pBlockTable->getAt(ACDB_MODEL_SPACE, pModelSpace, AcDb::kForRead);
	pBlockTable->close();

	// 迭代模型空间中的所有实体
	AcDbBlockTableRecordIterator *pIterator;
	pModelSpace->newIterator(pIterator);
	//定义一个矩形结构体数组
	std::vector<rectangle> rectangles;

	for (; !pIterator->done(); pIterator->step())
	{
		AcDbEntity *pEntity;
		pIterator->getEntity(pEntity, AcDb::kForRead);

		// 判断实体是否为多段线(长方形)
		if (pEntity->isKindOf(AcDbPolyline::desc()))
		{
			AcDbPolyline *pPolyline = AcDbPolyline::cast(pEntity);

			// 判断是否是闭合的多段线(长方形)
			if (pPolyline->isClosed())
			{
				// 获取长方形的名称
				ACHAR *name = pPolyline->layer();

				// 计算长方形的长度和宽度
				double length = 0.0;
				double width = 0.0;

				for (int i = 0; i < pPolyline->numVerts(); i++)
				{
					AcGePoint3d startPoint, endPoint;
					pPolyline->getPointAt(i, startPoint);
					pPolyline->getPointAt((i + 1) % pPolyline->numVerts(), endPoint); // Wrap around to the first point

					double segmentLength = startPoint.distanceTo(endPoint);

					if (segmentLength > length) {
						length = segmentLength;
					}

					if (i == 0) {
						width = segmentLength;
					}
					else {
						if (segmentLength < width) {
							width = segmentLength;
						}
					}
				}
				rectangle reg = {name,length,width};
				rectangles.push_back(reg);
			}
		}

		// 关闭对象
		//pObj->close();
		pEntity->close();
	}

	delete pIterator;
	pModelSpace->close();
	GenerateExcelDocument(rectangles);
}

void DeleteDocument(const std::string& filename) {
	std::ifstream file(filename);
	
	// 检查文件是否存在
	if (file.good()) {
		// 文件存在,删除文件
		if (std::remove(filename.c_str()) == 0) {
			std::cout << "File deleted successfully." << std::endl;
		}
		else {
			std::cout << "Error deleting file." << std::endl;
		}
	}
	//else {
	//	// 文件不存在,创建文件
	//	std::ofstream outfile(filename);
	//	if (outfile.is_open()) {
	//		std::cout << "File created successfully." << std::endl;
	//		outfile.close();
	//	}
	//	else {
	//		std::cout << "Error creating file." << std::endl;
	//	}
	//}

}



//把char字符转换为wchar
wchar_t* CharConvertWChar(char* str) {
	
	// 计算所需的宽字符长度(包括空字符结尾)
	int nameSize = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	// 分配内存来存储宽字符
	wchar_t* wideStr = new wchar_t[nameSize];
	// 将多字节字符转换为宽字符
	MultiByteToWideChar(CP_UTF8, 0, str, -1, wideStr, nameSize);
	// 记得释放分配的内存
	delete[] wideStr;
	return wideStr;
}

void NameAndKeySetWchar() {
	//libxl用户名
	char* name = "QT";
	//libxl注册key
	char* key = "windows-2f2227060dcaef076cb96d6ca1m4n9hb";//这里就是破解后获取的key,直接用这个,如果不行的话可以评论,我再贴上破解文件的地址
	Document::Name = CharConvertWChar(name);
	Document::Key = CharConvertWChar(key);
}
// 生成 Excel 文件保存长方形的属性
void GenerateExcelDocument(std::vector<rectangle> rectangles)
{	
	NameAndKeySetWchar();
	// 创建一个 Excel 工作簿对象
	libxl::Book* book = xlCreateBook();
	//使用注册码
	book->setKey(Document::Name,Document::Key);
	// 字体设置
	libxl::Font* textFont = book->addFont();
	textFont->setSize(8);
	textFont->setName(L"Century Gothic");
	// 格式设置
	libxl::Format* textFormat = book->addFormat();
	textFormat->setFont(textFont);
	textFormat->setAlignH(libxl::ALIGNH_LEFT);
	// 在工作簿中添加一个工作表
	libxl::Sheet* sheet = book->addSheet(L"矩形明细信息");
	// 设置工作表显示网格线
	sheet->setDisplayGridlines(true);
	//表格的行、列索引都从0开始
	sheet->setCol(0,0,20, textFormat);
	sheet->setCol(1,2,10, textFormat);
	//给第一行设置行高
	sheet->setRow(0,15);
	//给表格第一行写入列名
	sheet->writeStr(0,0,L"name");
	sheet->writeStr(0, 1, L"length");
	sheet->writeStr(0, 2, L"width");

	//循环赋值给execl的单元格
	for (int i = 1; i < rectangles.size() + 1; i++) {
		sheet->setRow(i, 15);
		rectangle reg = rectangles[i-1];
		sheet->writeStr(i, 0, reg.Name, textFormat);
		sheet->writeNum(i, 1, reg.Length, textFormat);
		sheet->writeNum(i, 2, reg.Width, textFormat);
	}
	wchar_t* filename = L"D:\\VisualStudio2022WorkSpace\\ArxProject3\\receipt.xls";
	std::string filename1 = "D:\\VisualStudio2022WorkSpace\\ArxProject3\\receipt.xls";
	char* filename2 = "D:\\VisualStudio2022WorkSpace\\ArxProject3\\receipt.xls";
	DeleteDocument(filename1);
	book->save(filename);
	book->release();

}


void Document::InitApp() {
	acedRegCmds->addCommand(L"Document",L"OutDocument",L"OutDocument", ACRX_CMD_TRANSPARENT, GetAllEntities);
}

void Document::UnLoad() {
	acedRegCmds->removeGroup(L"Document");
}


修改acrxEntryPoint.cpp,记得添加对Document头文件的引用

四、生成测试

1.生成解决方案

2.启动项目

3.Autocad使用命令appload加载生成的arx文件

4.绘制几个矩形

5.输入命令OUTDOCUMENT按下回车

6.打开生成的EXECL文件查看效果,一共绘制了四个矩形,所以EXECL中只记录了四个矩形的图层名称、长度、宽度信息

五、总结与思考

开发之前设想的需求是获取矩形的名称,但是在后续开发中发现绘制的矩形没有名称,他是一个多段线而组成的闭合多边形,所以我暂时理解为多段线是组成这种多边图形的基础单位,后续的开发中需要获取这种多边形的相关信息,可以通过多段线的属性或者再结合算法获取

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值