Однотипные строки в цикл

Автор Тема: Однотипные строки в цикл  (Прочитано 13818 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 381
  • Карма: 21
Однотипные строки в цикл
« : 22-10-2019, 19:57:15 »
Всех приветствую.

Имеется вот такие две части кода

Код - vb.net [Выбрать]
  1. Dim lxDesign As ResultBuffer = LispExtensions.GetLispSym("lxDesign")
  2. Dim lxDesignDate As ResultBuffer = LispExtensions.GetLispSym("lxDesignDate")
  3. Dim lxChecking As ResultBuffer = LispExtensions.GetLispSym("lxChecking")
  4. Dim lxCheckingDate As ResultBuffer = LispExtensions.GetLispSym("lxCheckingDate")

Код - vb.net [Выбрать]
  1. Dim lxArray As Array
  2. Dim lxString As String
  3.  
  4. lxArray = lxDesign.AsArray
  5. lxString = lxArray(0).value
  6. TB_11.Text = lxString
  7.  
  8. lxArray = lxDesignDate.AsArray
  9. lxString = lxArray(0).value
  10. TB_21.Text = lxString
  11.  
  12. lxArray = lxChecking.AsArray
  13. lxString = lxArray(0).value
  14. TB_12.Text = lxString
  15.  
  16. lxArray = lxCheckingDate.AsArray
  17. lxString = lxArray(0).value
  18. TB_22.Text = lxString
Это части кода, который создаёт окно. Логика работы такая - при инициализации берутся переменные лиспа, есть они или нет в чертеже. Потом заполняются или редактируются поля, считываются и отправляются обратно в переменные лиспа. Мне интересно, возможно ли записать данные примеры циклом, чтобы было меньше строк. В автолиспе я делал это через (eval (read variable)). В VB.NET не могу найти информацию и не хватает опыта.

Конструкция типа:
Код - vb.net [Выбрать]
  1. Dim lxStringCollection = New String() {"lxDesign", "lxDesignDate", "lxChecking", "lxCheckingDate"}
  2. Dim lxTBCollection = New String() {"TB_11", "TB_21", "TB_12", "TB_22"}
  3.  
  4. For lxItem = 0 To lxStringCollection.GetUpperBound(0)
  5.   lxResultBuffer.Add(LispExtensions.GetLispSym(lxItem))
  6. Next
  7.  
  8. Dim lxIndex = 0
  9. For Each lxBuffer As TypedValue In lxResultBuffer
  10.   Dim lxStringBuffer As String = lxTBCollection(lxIndex) & ".text = lxBuffer.Value"
  11.   Dim lxTable = New System.Data.DataTable()
  12.   Convert.ToDouble(lxTable.Compute(lxStringBuffer, Nothing))
  13.   lxIndex += 1
  14. Next
Вылетает с критической ошибкой AutoCAD.

И второй вопрос.
Первый вариант окна я делал с помощью класса, написанного Александром Ривилисом https://forums.autodesk.com/t5/net/acedgetsym-and-acedputsym-in-net-applications/td-p/1635754 и переработанного для VB.net https://www.theswamp.org/index.php?topic=35714.0. Но изучая хелп по API .NET я наткнулся на тот факт, что в API реализованы данные методы. Нашёл пример использования этих методов на C# https://adndevblog.typepad.com/autocad/2014/08/set-or-get-lisp-symbol-in-net.html. И метод Set* работал отлично, но метод Get* не хотел работать, при отладке выдавало исключение, если в переменной находилось значение String. Изначально я неправильно переписал код с C# на VB.NET. Когда я точно повторил пример на сайте, то уже выдавало не просто исключение, а указывало на то, что объект String не может быть сконвертирован в TypedValue.

Я решил проблему двумя способами:
Код - vb.net [Выбрать]
  1. Dim lxDesign As Object = lxDocument.GetLispSymbol("lxDesignPE4")
  2. If Not String.IsNullOrEmpty(lxDesign) Then
  3.   TB_11.Text = lxDesign.ToString
  4. End If
Код - vb.net [Выбрать]
  1. Dim lxDesign = New TypedValue(CInt(LispDataType.Text), lxDocument.GetLispSymbol("lxDesignPE4"))
  2. TB_11.Text = lxDesign.Value
И если кто может объяснить чем эти способы различаются и могут повлиять на AutoCAD. Либо они равнозначны и можно делать как удобно.

PS Прошу особо не пинать за, может быть, глупые и непонятные вопросы, изучаю AutoLISP с лета этого года, а VB.NET пару недель.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #1 : 22-10-2019, 21:09:33 »
Приветствую на форуме!
изучаю AutoLISP с лета этого года, а VB.NET пару недель.
Рекомендую бросить изучать VB.NET и начать изучать C#.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #2 : 22-10-2019, 21:17:35 »
Вылетает с критической ошибкой AutoCAD.
Что говорит пошаговая отладка? И что за критическая ошибка?
Я решил проблему двумя способами:
Как по мне первый вариант предпочтительней, но особой разницы (особенно на VB.NET) я не вижу.

P.S.: Однозначно одна из ошибок здесь:
Код - vb.net [Выбрать]
  1. For lxItem = 0 To lxStringCollection.GetUpperBound(0)
  2.   lxResultBuffer.Add(LispExtensions.GetLispSym(lxItem))
  3. Next
Должно быть как-то так (на VB.NET не пишу):
Код - vb.net [Выбрать]
  1. For lxItem = 0 To lxStringCollection.GetUpperBound(0)
  2.   lxResultBuffer.Add(LispExtensions.GetLispSym(lxStringCollection(lxItem)))
  3. Next
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #3 : 22-10-2019, 21:51:20 »
Нашёл пример использования этих методов на C# https://adndevblog.typepad.com/autocad/2014/08/set-or-get-lisp-symbol-in-net.html. И метод Set* работал отлично, но метод Get* не хотел работать, при отладке выдавало исключение, если в переменной находилось значение String.
Похоже, что в статье ошибка, о чем в комментарии к ней написано. Document.GetLispSymbol возвращает Object, а не TypedValue.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 381
  • Карма: 21
Re: Однотипные строки в цикл
« Ответ #4 : 22-10-2019, 22:01:46 »
Рекомендую бросить изучать VB.NET и начать изучать C#.
Александр, а можете вкратце объяснить почему C# предпочтительнее? Я читал закреплённые темы Андрея Бушмана про книги и тему про изучение C#, но пока что не понял преимущества C# над VB.NET.

AutoCAD вылетает при операции добавления в ResultBuffer.
Код - vb.net [Выбрать]
  1. For lxItem = 0 To lxStringCollection.GetUpperBound(0)
  2.   lxResultBuffer.Add(LispExtensions.GetLispSym(lxStringCollection(lxItem)))
  3. Next

Он объявляется глобально
Код - vb.net [Выбрать]
  1. Public lxResultBuffer As ResultBuffer

Похоже, что в статье ошибка, о чем в комментарии к ней написано. Document.GetLispSymbol возвращает Object, а не TypedValue.
Вы правы, я в хелпе сразу видел, что он возвращает Object, но так как не имею своего опыта, понадеялся на опыт человека, написавшего статью.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #5 : 22-10-2019, 22:09:33 »
Александр, а можете вкратце объяснить почему C# предпочтительнее?
Вкратце - на C# значительно больше примеров, он красивее, лаконичнее, роднее для .NET
VB.NET - это искусственное образование из учебного Basic, с грехом пополам адаптированное для работы с .NET
Лично мне крайне неприятно читать код, написанный на нём.
Он объявляется глобально
Код - vb.net [Выбрать]

    Public lxResultBuffer As ResultBuffer
А где оно инициализировано? Должно быть где-то
Код - vb.net [Выбрать]
  1. lxResultBuffer = new ResultBuffer()
до вызовов lxResultBuffer.Add(...).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 381
  • Карма: 21
Re: Однотипные строки в цикл
« Ответ #6 : 22-10-2019, 22:35:11 »
А где оно инициализировано? Должно быть где-то
Я думал, что инициализация происходит во время объявления глобальной переменной. Я добавил инициализацию перед выполнением цикла, ничего не изменилось. Хочу заметить, что AutoCAD крашится независимо от того есть ли в чертеже переменная, либо она просто пустая, либо с данными String.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #7 : 22-10-2019, 22:39:17 »
Я думал, что инициализация происходит во время объявления глобальной переменной.
Нет.
Хочу заметить, что AutoCAD крашится независимо от того есть ли в чертеже переменная, либо она просто пустая, либо с данными String.
А если вместо LispExtensions.GetLispSym() используешь lxDocument.GetLispSymbol(...) ?
Какая версия и разрядность AutoCAD? Где код LispExtensions.GetLispSym?
Вообще-то после появления в AutoCAD .NET API методов Document.GetLispSymbol/Document.SetLispSymbol потребность в использовании P/Invoke для acedGetSym/acedSetSym отпала. Тем более, что использование их сопряжено с определенными сложностями (начиная с AutoCAD 2013 вместо "acad.exe" используется "accore.dll" и сигнатура функции претерпела изменения - вместо "acedGetSym" в AutoCAD 2020 x64 "?acedGetSym@@YAHPEB_WPEAPEAUresbuf@@@Z").
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 381
  • Карма: 21
Re: Однотипные строки в цикл
« Ответ #8 : 22-10-2019, 23:01:04 »
А если вместо LispExtensions.GetLispSym() используешь lxDocument.GetLispSymbol(...) ?
Это я уже завтра потестирую

Какая версия и разрядность AutoCAD?
Простой английский AutoCAD x64.

Где код LispExtensions.GetLispSym?
Код брал вот отсюда http://www.theswamp.org/index.php?topic=35714.msg460016#msg460016 , там же и упоминается о том, что произошли изменения после 2013 версии.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #9 : 22-10-2019, 23:01:51 »
Простой английский AutoCAD x64.
Версия какая???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 381
  • Карма: 21
Re: Однотипные строки в цикл
« Ответ #10 : 22-10-2019, 23:07:06 »
Простой английский AutoCAD x64.
Версия какая???
Блин, я уже сплю  :) Версия 2018

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #11 : 22-10-2019, 23:08:41 »
Блин, я уже сплю  :) Версия 2018
Теоретически замена "acad.exe" на "accore.dll" должна была помочь. Завтра проверю.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 381
  • Карма: 21
Re: Однотипные строки в цикл
« Ответ #12 : 22-10-2019, 23:20:18 »
Блин, я уже сплю  :) Версия 2018
Теоретически замена "acad.exe" на "accore.dll" должна была помочь. Завтра проверю.

Так если я делаю без цикла, а просто

Код - vb.net [Выбрать]
  1. Dim lxDesign As ResultBuffer = LispExtensions.GetLispSym("lxDesign")

то всё работает.

Я ведь правильно понимаю, что метод Add аналогичен вот такому добавлению?

Код - vb.net [Выбрать]
  1. Dim input As New ResultBuffer(
  2. New TypedValue(CInt(LispDataType.ListBegin)),
  3. New TypedValue(CInt(LispDataType.Int16), 12),
  4. New TypedValue(CInt(LispDataType.Text), "toto"),
  5. New TypedValue(CInt(LispDataType.T_atom)),
  6. New TypedValue(CInt(LispDataType.ListEnd)))
Хотя, пример со списком не совсем корректен...

И ещё хочу уточнить, что мне нужно получить не список строк для лиспа, а мне нужен массив ResultBuffer. Но я пытался сделать вот так
Код - vb.net [Выбрать]
  1. Public lxDesign As ResultBuffer()
При добавлении в массив по индексу AutoCAD уже не крашился, а вылетало исключение при следующей итерации.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Однотипные строки в цикл
« Ответ #13 : 23-10-2019, 09:09:20 »
Я ведь правильно понимаю, что метод Add аналогичен вот такому добавлению?
Вообще-то ResultBuffer.Add работает с TypedValue, а не с ResultBuffer. В этом может быть ошибка.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Однотипные строки в цикл
« Ответ #14 : 23-10-2019, 11:00:40 »
Имеется вот такие две части кода

Код - vb.net [Выбрать]
  1. Dim lxDesign As ResultBuffer = LispExtensions.GetLispSym("lxDesign")
  2. Dim lxDesignDate As ResultBuffer = LispExtensions.GetLispSym("lxDesignDate")
  3. Dim lxChecking As ResultBuffer = LispExtensions.GetLispSym("lxChecking")
  4. Dim lxCheckingDate As ResultBuffer = LispExtensions.GetLispSym("lxCheckingDate")

Код - vb.net [Выбрать]
  1. Dim lxArray As Array
  2. Dim lxString As String
  3.  
  4. lxArray = lxDesign.AsArray
  5. lxString = lxArray(0).value
  6. TB_11.Text = lxString
  7.  
  8. lxArray = lxDesignDate.AsArray
  9. lxString = lxArray(0).value
  10. TB_21.Text = lxString
  11.  
  12. lxArray = lxChecking.AsArray
  13. lxString = lxArray(0).value
  14. TB_12.Text = lxString
  15.  
  16. lxArray = lxCheckingDate.AsArray
  17. lxString = lxArray(0).value
  18. TB_22.Text = lxString
Это части кода, который создаёт окно. Логика работы такая - при инициализации берутся переменные лиспа, есть они или нет в чертеже. Потом заполняются или редактируются поля, считываются и отправляются обратно в переменные лиспа. Мне интересно, возможно ли записать данные примеры циклом, чтобы было меньше строк. В автолиспе я делал это через (eval (read variable)). В VB.NET не могу найти информацию и не хватает опыта.

Конструкция типа:
Код - vb.net [Выбрать]
  1. Dim lxStringCollection = New String() {"lxDesign", "lxDesignDate", "lxChecking", "lxCheckingDate"}
  2. Dim lxTBCollection = New String() {"TB_11", "TB_21", "TB_12", "TB_22"}
  3.  
  4. For lxItem = 0 To lxStringCollection.GetUpperBound(0)
  5.   lxResultBuffer.Add(LispExtensions.GetLispSym(lxItem))
  6. Next
  7.  
  8. Dim lxIndex = 0
  9. For Each lxBuffer As TypedValue In lxResultBuffer
  10.   Dim lxStringBuffer As String = lxTBCollection(lxIndex) & ".text = lxBuffer.Value"
  11.   Dim lxTable = New System.Data.DataTable()
  12.   Convert.ToDouble(lxTable.Compute(lxStringBuffer, Nothing))
  13.   lxIndex += 1
  14. Next
Вылетает с критической ошибкой AutoCAD.
Это потому, что, несмотря на использование .NET, Вы продолжаете думать на LISP. То есть, Вы совершенно игнорируете новые возможности и пытаетесь адаптировать .NET под логику LISP. Разумеется, что ничего хорошего из этого не выйдет.
Как вариант, что можно сделать.
1. Вместо двух несвязанных между собой коллекций из названий переменных и имён текстбоксов можно создать словарь Dictionary<string, TextBox> с ключом-строкой с именем переменной и соответствующим ему значением типа TextBox (в .NET можно создавать коллекции из объектов) вида: ["lxDesign" - TB_11], ["lxDesignDate" - TB_21], ["lxChecking", TB_12]
2. Пройтись foreach по этому словарю, беря по очереди ключ и значение и выполняя операцию по занесению значения переменной в текстбокс.
На VB.NET не пишу, поэтому, примера не будет.