Вопрос: Есть картинка в RT поле и надо поверх картинки написать текст. Как такое можно сделать?

Обмена параметрами не надо.
На диске рядом лежат 2 папки, например: \AddWatermark_in и \AddWatermark_out. Код на LS кладёт файл в первую папку. Через LS2J вызываете Java-метод, в него передаёте параметром имя файла. Java-код открывает файл из 1-й папки, после обработки кладёт файл результата с тем же именем во 2-ю папку, а из 1-й удаляет. LS-код забирает результат из 2-й папки по тому же имени. При таком подходе вереница из агентов ненужна.
Либо просто написать Java-агент. Лично я бы для такой задачи выбрал обработку очереди таких писем-запросов на сервере Java-агентом.
из LS2J можно сразу гонять java *Stream
пример обмена из HTTP запроса
Visual Basic:
    Function joProcess()
        On Error GoTo ErrH
        me.joCon.setRequestMethod(me.method_)
        Dim in_ As Javaobject, clreader As Javaclass, clBuf As Javaclass, is_ As Javaobject
        Dim os_ As Javaobject, osw_ As Javaobject, clWriter As Javaclass
        If Len(me.body_)>0 Then
            Call joCon.setDoOutput(True)
            Set os_ = joCon.getOutputStream()
            Set clWriter=jSession.GetClass(WRITER_CL)
            Set osw_=clWriter.CreateObject({(L} & OUTSTREAM_CL &{;Ljava/lang/String;)V}, os_, {UTF-8})
            osw_.write(me.body_)
            Call osw_.flush()
            Call osw_.close()
            Call os_.close()
            Call joCon.connect()
        End If
'        On Error 318 GoTo jErr
        Set is_=joCon.getInputStream()
        Dim ret As String
        ret=me.joStreamProcessing.getBuffer(is_).toString()
        me.responseCode_=joCon.getResponseMessage()
        If joCon.getResponseCode()=200 Then
            '    me.responseCode_=CStr(joCon.getResponseCode()) & { OK}
            Set me.headers_=joCon.getHeaderFields()
        Else
        End If
        joProcess=ret
блок констант
Visual Basic:
Private Const HTTPCLIENT_CL={java/net/http/HttpClient}
Private Const HTTPREQUEST_CL={java/net/http/HttpRequest}
Private Const HTTPRESPONSE_CL={java/net/http/HttpResponse}
Private Const STRING_CL={java/lang/String}
Private Const STRINGBUF_CL={java/lang/StringBuffer}
местами неудобно манипулировать java объектами (со сложно в..банной обработкой) - тогда пишем рапер, например:
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamProcessing {
    
    public StringBuffer getBuffer(InputStream is) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        String output;

        StringBuffer response = new StringBuffer();
        while ((output = in.readLine()) != null) {
            response.append(output);
        }

        in.close();
        return response;
        
    }
}
 
java агенты, если надо с нотусячими сущностями, я не лю
 
Я сейчас пытаюсь выбрать для себя оптимальное решение: или изучать java для Lotus, или пытаться использовать dll библиотеки Twain - это мне ближе. Был опыт по кнопке в лотус документе делать скан с USB сканера в pdf и прикрепить полученный файл pdf в RT поле открытого лотусового документа.
На днях пытался с maven поработать - то еще приключение! )))
 
Последнее редактирование:
На примере

Делаете 2 библиотеки

Первую на java вторую на lotusscript, тестируете, как работает.

Затем по аналогии делаете добавление текста на картинку, используя ссылку, которую выше прислал lmike
В вашем случае у функции, как в ls так и в java будут входные параметры, в которых из ls вы передадите путь к файлу, текст, координаты куда писать текст на картинке.


код на java в библиотеке utilsJava

Код:
public class utils {
    public static String getTmpDir() {
        String tempdir = System.getProperty("java.io.tmpdir");
        String sep = System.getProperty("file.separator");
        return !tempdir.endsWith(sep) ?  tempdir.concat(sep) : tempdir;  
    }  
}

вторая на lotusscript библиотека "utils"

Код:
%Include "lsxsd.lss"
UseLSX "*javacon"
Use "utilsJava"


Function getTmpDir() As String
    On Error GoTo ErrorHandler
    Dim jSession As New JavaSession
    Dim jClass As JavaClass
    Set jClass = jSession.Getclass("utils")
    Dim jObject As JavaObject
    Set jObject = jClass.Createobject()
    getTmpDir = jObject.getTmpDir()  
 Exit function
 
Попробовал по учебнику java для лотусистов написать простенькие библиотечки на java и на LS с вызовом LS2J на локальном компе. Суть заключается в том, что бы вызвать лотус сессию на java. Ошибок - море. Пробовал разобраться - это какой-то мазохизм!!! Что будет, если этот код выложить на серверную базу - ***дец!
 
Попробовал по учебнику java для лотусистов написать простенькие библиотечки на java и на LS с вызовом LS2J на локальном компе. Суть заключается в том, что бы вызвать лотус сессию на java. Ошибок - море. Пробовал разобраться - это какой-то мазохизм!!! Что будет, если этот код выложить на серверную базу - ***дец!
сходу - LDN сущности запрещены к использованию через бридж!
LS2J - это использование java из LDN
т.е. расширяет возможности LS штатными возможностями java, , без lotus.* классов
никому же в голову не приходило звать COM из LDN и в нём открывать LDN сущности ;)
 
На примере

Делаете 2 библиотеки

Первую на java вторую на lotusscript, тестируете, как работает.

На примере

Делаете 2 библиотеки

Первую на java вторую на lotusscript, тестируете, как работает.

...
можно из без java-библиотеки
Код:
    Dim jSession As JavaSession
    Dim SysClass As JavaClass
    Dim System  As JavaObject
    '....
        Set jSession = New JavaSession
        Set SysClass=jSession.GetClass({java.lang.System})
        Set System = sysClass.CreateObject()  
    '...
        Dim sep$, tmp$
       
        sep$ = System.getProperty("file.separator")
        tmp$ = System.getProperty("java.io.tmpdir")
       
        If Right(tmp$,1)<>sep$ Then tmp$=tmp$+sep$
        TempPath = tmp$
как-то так (кусочек из класса своего выдрал так что +/-)
ну и следовательно все остальные свойства можно вычленить если что
Код:
' возвращает строку используемую на текущей платформе как разделитель строк (win 13+10, lin 10)
LineSeparator = Me.System.getProperty("line.separator")

' возвращает название текущей ОС
OSName = Me.System.getProperty("os.name")

' возвращает версию текущей ОC
OSVersion = Me.System.getProperty("os.version")

'...
UserName = Me.System.getProperty("user.name")
jVers = System.getProperty("java.version")
 
  • Нравится
Реакции: VladSh
можно из без java-библиотеки
Код:
    Dim jSession As JavaSession
    Dim SysClass As JavaClass
    Dim System  As JavaObject
    '....
        Set jSession = New JavaSession
        Set SysClass=jSession.GetClass({java.lang.System})
        Set System = sysClass.CreateObject() 
    '...
        Dim sep$, tmp$
      
        sep$ = System.getProperty("file.separator")
        tmp$ = System.getProperty("java.io.tmpdir")
      
        If Right(tmp$,1)<>sep$ Then tmp$=tmp$+sep$
        TempPath = tmp$
как-то так (кусочек из класса своего выдрал так что +/-)
ну и следовательно все остальные свойства можно вычленить если что
Код:
' возвращает строку используемую на текущей платформе как разделитель строк (win 13+10, lin 10)
LineSeparator = Me.System.getProperty("line.separator")

' возвращает название текущей ОС
OSName = Me.System.getProperty("os.name")

' возвращает версию текущей ОC
OSVersion = Me.System.getProperty("os.version")

'...
UserName = Me.System.getProperty("user.name")
jVers = System.getProperty("java.version")
для незамороченных случаев - вполне
если сложные конструкторы - проще своим классом накрыть
 
Короче получилось средствами LS + DLL! Только в надписи почемуто прорисовались столбцы, разделяющие буквы.
 

Вложения

  • 0.jpg.webp
    0.jpg.webp
    57,2 КБ · Просмотры: 35
Короче получилось средствами LS + DLL! Только в надписи почемуто прорисовались столбцы, разделяющие буквы.
мда...
попросил deepseek
напиши код на lotusscript и LS2J наложения текста на картинку

результат (не проверял,, местами похоже):
Markdown (GitHub flavored):
Наложение текста на изображение с использованием LotusScript и LS2J (LotusScript to Java) может быть выполнено с использованием Java-библиотек, таких как `java.awt` и `javax.imageio`. LotusScript сам по себе не имеет встроенных функций для работы с изображениями, поэтому мы будем использовать LS2J для вызова Java-кода.

Вот пример кода на LotusScript, который использует LS2J для наложения текста на изображение:

### LotusScript код:

```lotusscript
Option Public
Option Declare

UseLSX "*javacon"

Sub Initialize
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim doc As NotesDocument
    Set db = session.CurrentDatabase
    Set doc = db.CreateDocument

    ' Путь к исходному изображению и выходному файлу
    Dim imagePath As String
    Dim outputPath As String
    imagePath = "C:\path\to\input\image.jpg"
    outputPath = "C:\path\to\output\image_with_text.jpg"

    ' Текст для наложения
    Dim textToAdd As String
    textToAdd = "Hello, World!"

    ' Вызов Java-кода через LS2J
    Dim javaSession As JAVASESSION
    Dim javaClass As JAVACLASS
    Dim javaObject As JAVACLASS
    Set javaSession = New JAVASESSION
    Set javaClass = javaSession.GetClass("com.example.ImageTextOverlay")
    Set javaObject = javaClass.CreateObject()

    ' Вызов метода для наложения текста
    Call javaObject.OverlayText(imagePath, outputPath, textToAdd)

    ' Сохранение документа
    doc.Form = "MainForm"
    doc.Subject = "Image with Text Overlay"
    doc.Body = "Text added to image: " & textToAdd
    Call doc.Save(True, False)

    Print "Text has been added to the image and saved to " & outputPath
End Sub
```

### Java код (ImageTextOverlay.java):

```java
package com.example;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageTextOverlay {

    public void OverlayText(String imagePath, String outputPath, String text) {
        try {
            // Загрузка изображения
            File file = new File(imagePath);
            BufferedImage image = ImageIO.read(file);

            // Создание графического контекста
            Graphics2D g2d = image.createGraphics();

            // Настройка шрифта и цвета текста
            g2d.setColor(Color.RED);
            g2d.setFont(new Font("Arial", Font.BOLD, 48));

            // Наложение текста на изображение
            g2d.drawString(text, 50, 50);

            // Освобождение ресурсов
            g2d.dispose();

            // Сохранение измененного изображения
            File outputFile = new File(outputPath);
            ImageIO.write(image, "jpg", outputFile);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```

### Инструкции:

1. **Создание Java-класса**:
   - Создайте Java-класс `ImageTextOverlay` в пакете `com.example`.
   - Скомпилируйте этот класс и добавьте его в classpath вашего Domino-сервера.

2. **Настройка LS2J**:
   - Убедитесь, что LS2J правильно настроен на вашем сервере Domino.
   - Добавьте `javacon.lbx` в ваш скрипт LotusScript.

3. **Запуск кода**:
   - Запустите LotusScript-код в Notes/Domino, чтобы наложить текст на изображение.

Этот код загружает изображение, накладывает на него текст и сохраняет результат в новый файл. Вы можете настроить шрифт, цвет и положение текста в Java-коде по вашему усмотрению.
 
  • Нравится
Реакции: VladSh
попросил
добавь в lotusscript код дл размещения результата в том же поле NotesDocument
Visual Basic:
Option Public
Option Declare

UseLSX "*javacon"

Sub Initialize
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim doc As NotesDocument
    Set db = session.CurrentDatabase

    ' Получаем документ, из которого будем извлекать изображение
    Set doc = db.GetDocumentByUNID("UNID_вашего_документа") ' Замените на UNID нужного документа

    ' Проверяем, существует ли документ
    If doc Is Nothing Then
        Print "Документ не найден!"
        Exit Sub
    End If

    ' Поле RichText, содержащее изображение
    Dim rtItem As NotesRichTextItem
    Set rtItem = doc.GetFirstItem("Body") ' Замените "Body" на имя вашего RichText-поля

    ' Проверяем, существует ли поле
    If rtItem Is Nothing Then
        Print "Поле RichText не найдено!"
        Exit Sub
    End If

    ' Временный файл для сохранения изображения
    Dim tempImagePath As String
    tempImagePath = "C:\temp\image_from_richtext.jpg"

    ' Извлекаем изображение из RichText и сохраняем его во временный файл
    If Not ExtractImageFromRichText(rtItem, tempImagePath) Then
        Print "Не удалось извлечь изображение из RichText!"
        Exit Sub
    End If

    ' Путь для сохранения результата
    Dim outputPath As String
    outputPath = "C:\temp\image_with_text.jpg"

    ' Текст для наложения
    Dim textToAdd As String
    textToAdd = "Hello, World!"

    ' Вызов Java-кода через LS2J
    Dim javaSession As JAVASESSION
    Dim javaClass As JAVACLASS
    Dim javaObject As JAVACLASS
    Set javaSession = New JAVASESSION
    Set javaClass = javaSession.GetClass("com.example.ImageTextOverlay")
    Set javaObject = javaClass.CreateObject()

    ' Вызов метода для наложения текста
    Call javaObject.OverlayText(tempImagePath, outputPath, textToAdd)

    ' Удаляем старое содержимое RichText-поля
    Call rtItem.Remove

    ' Создаем новое RichText-поле и добавляем в него обработанное изображение
    Set rtItem = doc.CreateRichTextItem("Body") ' Замените "Body" на имя вашего RichText-поля
    Call rtItem.EmbedObject(EMBED_ATTACHMENT, "", outputPath)

    ' Сохраняем документ
    Call doc.Save(True, False)

    ' Очистка временных файлов
    Kill tempImagePath
    Kill outputPath

    Print "Текст успешно наложен на изображение. Результат сохранен в поле RichText документа."
End Sub

Function ExtractImageFromRichText(rtItem As NotesRichTextItem, filePath As String) As Boolean
    On Error GoTo HandleError

    ' Получаем все вложения в RichText
    Dim embedObj As NotesEmbeddedObject
    Set embedObj = rtItem.GetEmbeddedObject(1) ' Предполагаем, что изображение — первое вложение

    ' Проверяем, что вложение существует
    If embedObj Is Nothing Then
        Print "В RichText нет вложений!"
        ExtractImageFromRichText = False
        Exit Function
    End If

    ' Сохраняем вложение как временный файл
    Call embedObj.ExtractFile(filePath)

    ExtractImageFromRichText = True
    Exit Function

HandleError:
    Print "Ошибка при извлечении изображения: " & Error$
    ExtractImageFromRichText = False
End Function
на всё потратил минут 5-ть с переносом сюда кода и беглой оценкой
а здесь уже намотали вторую страницу переписки и результат: всратая ДЛЛ ;)
 
мда...
попросил deepseek


результат (не проверял,, местами похоже):
Markdown (GitHub flavored):
Наложение текста на изображение с использованием LotusScript и LS2J (LotusScript to Java) может быть выполнено с использованием Java-библиотек, таких как `java.awt` и `javax.imageio`. LotusScript сам по себе не имеет встроенных функций для работы с изображениями, поэтому мы будем использовать LS2J для вызова Java-кода.

Вот пример кода на LotusScript, который использует LS2J для наложения текста на изображение:

### LotusScript код:

```lotusscript
Option Public
Option Declare

UseLSX "*javacon"

Sub Initialize
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim doc As NotesDocument
    Set db = session.CurrentDatabase
    Set doc = db.CreateDocument

    ' Путь к исходному изображению и выходному файлу
    Dim imagePath As String
    Dim outputPath As String
    imagePath = "C:\path\to\input\image.jpg"
    outputPath = "C:\path\to\output\image_with_text.jpg"

    ' Текст для наложения
    Dim textToAdd As String
    textToAdd = "Hello, World!"

    ' Вызов Java-кода через LS2J
    Dim javaSession As JAVASESSION
    Dim javaClass As JAVACLASS
    Dim javaObject As JAVACLASS
    Set javaSession = New JAVASESSION
    Set javaClass = javaSession.GetClass("com.example.ImageTextOverlay")
    Set javaObject = javaClass.CreateObject()

    ' Вызов метода для наложения текста
    Call javaObject.OverlayText(imagePath, outputPath, textToAdd)

    ' Сохранение документа
    doc.Form = "MainForm"
    doc.Subject = "Image with Text Overlay"
    doc.Body = "Text added to image: " & textToAdd
    Call doc.Save(True, False)

    Print "Text has been added to the image and saved to " & outputPath
End Sub
```

### Java код (ImageTextOverlay.java):

```java
package com.example;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageTextOverlay {

    public void OverlayText(String imagePath, String outputPath, String text) {
        try {
            // Загрузка изображения
            File file = new File(imagePath);
            BufferedImage image = ImageIO.read(file);

            // Создание графического контекста
            Graphics2D g2d = image.createGraphics();

            // Настройка шрифта и цвета текста
            g2d.setColor(Color.RED);
            g2d.setFont(new Font("Arial", Font.BOLD, 48));

            // Наложение текста на изображение
            g2d.drawString(text, 50, 50);

            // Освобождение ресурсов
            g2d.dispose();

            // Сохранение измененного изображения
            File outputFile = new File(outputPath);
            ImageIO.write(image, "jpg", outputFile);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```

### Инструкции:

1. **Создание Java-класса**:
   - Создайте Java-класс `ImageTextOverlay` в пакете `com.example`.
   - Скомпилируйте этот класс и добавьте его в classpath вашего Domino-сервера.

2. **Настройка LS2J**:
   - Убедитесь, что LS2J правильно настроен на вашем сервере Domino.
   - Добавьте `javacon.lbx` в ваш скрипт LotusScript.

3. **Запуск кода**:
   - Запустите LotusScript-код в Notes/Domino, чтобы наложить текст на изображение.

Этот код загружает изображение, накладывает на него текст и сохраняет результат в новый файл. Вы можете настроить шрифт, цвет и положение текста в Java-коде по вашему усмотрению.
в рекомендациях бота есть неточности:
- цомпилять не надо и путь прописывать
- Use уже есть нужный, предложен к-то херня
но сути не меняет ;)
 
  • Нравится
Реакции: VladSh
в рекомендациях бота есть неточности:
- цомпилять не надо и путь прописывать
- Use уже есть нужный, предложен к-то херня
но сути не меняет ;)
встроить в майм (как и извлечь и встроенной картинки в теле письма) - тоже можно попросить, но я уже поленился, уверен - сделает, с подсказками и коррекцией
 
Последнее редактирование:
на основе накида либу (поправил нек. ошибки)
Visual Basic:
%REM
    Library image-tools.LS2J
    Created Mar 23, 2025 by Mikhail Cholokov/lmike
    Description: Comments for Library
%END REM
Option Public
Option Declare
'UseLSX "*javacon"
Use "image-tools.java"
Sub Initialize

End Sub

    
Function ExtractImageFromRichText(rtItem As NotesRichTextItem, filePath As String)
    On Error GoTo ErrH
    GoTo Begin
ErrH:
    Error Err, "Ошибка в " & GetThreadInfo(1) & ", строка " & CStr(Erl) & ": " & Error$
Begin:
    
    If ( rtitem.Type = RICHTEXT ) Then
        Dim i As Integer
        ForAll o In rtitem.EmbeddedObjects
            If ( o.Type = EMBED_ATTACHMENT ) Then
                ExtractImageFromRichText=filepath & o.Source
                o.ExtractFile ExtractImageFromRichText
            End If
            i=i+1
        End ForAll
        If i<1 Then Error 1024, {В RichText нет вложений!}
    Else
        Error 1024, {тип поля нет RichText: } &rtitem.Type
    End If
    ' Получаем все вложения в RichText
'    Dim embedObj As NotesEmbeddedObject
'    Set embedObj = rtItem.GetEmbeddedObject(1) ' Предполагаем, что изображение — первое вложение

    ' Проверяем, что вложение существует
'    If embedObj Is Nothing Then
'        Print "В RichText нет вложений!"
'        ExtractImageFromRichText = False
'        Exit Function
'    End If

    ' Сохраняем вложение как временный файл
 '   Call embedObj.ExtractFile(filePath)

End Function
%REM
    Function TextOverImage
    Description: Comments for Function
%END REM
Function TextOverImage(doc As NotesDocument)
    On Error GoTo ErrH
    GoTo Begin
ErrH:
    Error Err, "Ошибка в " & GetThreadInfo(1) & ", строка " & CStr(Erl) & ": " & Error$
Begin:

    Dim session As New NotesSession

    ' Проверяем, существует ли документ
    If doc Is Nothing Then
        Print "Документ не найден!"
        Exit Function
    End If

    ' Поле RichText, содержащее изображение
    Dim rtItem As NotesRichTextItem
    Set rtItem = doc.GetFirstItem("Body") ' Замените "Body" на имя вашего RichText-поля

    ' Проверяем, существует ли поле
    If rtItem Is Nothing Then
        Print "Поле RichText не найдено!"
        Exit Function
    End If

    ' Временный файл для сохранения изображения
    Dim tempImagePath As String
    tempImagePath = "C:\temp\"
    tempImagePath = ExtractImageFromRichText(rtItem, tempImagePath)
    ' Извлекаем изображение из RichText и сохраняем его во временный файл
    If Len(tempImagePath)<4 Then
        Error 1024, "Не удалось извлечь изображение из RichText!"
    End If

    ' Путь для сохранения результата
    Dim outputPath As String, ext As String
    ext=StrRightBack(tempImagePath,{.})
    outputPath = StrLeft(tempImagePath,{.}) &{+text.} &ext

    ' Текст для наложения
    Dim textToAdd As String
    textToAdd = "Hello, World!"

    ' Вызов Java-кода через LS2J
    Dim javaSession As JAVASESSION
    Dim javaCl As JAVACLASS
    Dim javaObj As JAVAOBJECT
    Set javaSession = New JAVASESSION
    Set javaCl = javaSession.GetClass("com.example.ImageTextOverlay")
    Set javaObj = javaCl.Createobject()

    ' Вызов метода для наложения текста
    Call javaObj.OverlayText(tempImagePath, outputPath, textToAdd)

    ' Удаляем старое содержимое RichText-поля
    Call rtItem.Remove

    ' Создаем новое RichText-поле и добавляем в него обработанное изображение
    Set rtItem = doc.CreateRichTextItem("Body") ' Замените "Body" на имя вашего RichText-поля
    Call rtItem.EmbedObject(EMBED_ATTACHMENT, "", outputPath)

    ' Сохраняем документ
    Call doc.Save(True, False)

    ' Очистка временных файлов
    Kill tempImagePath
    Kill outputPath

    Print "Текст успешно наложен на изображение. Результат сохранен в поле RichText документа."
End Function
и агент
Visual Basic:
%REM
    Agent image-tools
    Created Mar 23, 2025 by Mikhail Cholokov/lmike
    Description: Comments for Agent
%END REM
Option Public
Option Declare
Use "image-tools.LS2J"
Sub Initialize
On Error GoTo ErrH
GoTo Begin
ErrH:
    Error Err, "Ошибка в " & GetThreadInfo(1) & ", строка " & CStr(Erl) & ": " & Error$
Begin:
    Dim agent As NotesAgent, ses As New NotesSession, db As NotesDatabase
    Set agent = ses.Currentagent
    Dim doc As NotesDocument
    Set doc=ses.Documentcontext
    TextOverImage doc

End Sub
результат
1742762128488.webp
 
на основе накида либу (поправил нек. ошибки)
Visual Basic:
%REM
    Library image-tools.LS2J
    Created Mar 23, 2025 by Mikhail Cholokov/lmike
    Description: Comments for Library
%END REM
Option Public
Option Declare
'UseLSX "*javacon"
Use "image-tools.java"
Sub Initialize

End Sub

 
Function ExtractImageFromRichText(rtItem As NotesRichTextItem, filePath As String)
    On Error GoTo ErrH
    GoTo Begin
ErrH:
    Error Err, "Ошибка в " & GetThreadInfo(1) & ", строка " & CStr(Erl) & ": " & Error$
Begin:
 
    If ( rtitem.Type = RICHTEXT ) Then
        Dim i As Integer
        ForAll o In rtitem.EmbeddedObjects
            If ( o.Type = EMBED_ATTACHMENT ) Then
                ExtractImageFromRichText=filepath & o.Source
                o.ExtractFile ExtractImageFromRichText
            End If
            i=i+1
        End ForAll
        If i<1 Then Error 1024, {В RichText нет вложений!}
    Else
        Error 1024, {тип поля нет RichText: } &rtitem.Type
    End If
    ' Получаем все вложения в RichText
'    Dim embedObj As NotesEmbeddedObject
'    Set embedObj = rtItem.GetEmbeddedObject(1) ' Предполагаем, что изображение — первое вложение

    ' Проверяем, что вложение существует
'    If embedObj Is Nothing Then
'        Print "В RichText нет вложений!"
'        ExtractImageFromRichText = False
'        Exit Function
'    End If

    ' Сохраняем вложение как временный файл
 '   Call embedObj.ExtractFile(filePath)

End Function
%REM
    Function TextOverImage
    Description: Comments for Function
%END REM
Function TextOverImage(doc As NotesDocument)
    On Error GoTo ErrH
    GoTo Begin
ErrH:
    Error Err, "Ошибка в " & GetThreadInfo(1) & ", строка " & CStr(Erl) & ": " & Error$
Begin:

    Dim session As New NotesSession

    ' Проверяем, существует ли документ
    If doc Is Nothing Then
        Print "Документ не найден!"
        Exit Function
    End If

    ' Поле RichText, содержащее изображение
    Dim rtItem As NotesRichTextItem
    Set rtItem = doc.GetFirstItem("Body") ' Замените "Body" на имя вашего RichText-поля

    ' Проверяем, существует ли поле
    If rtItem Is Nothing Then
        Print "Поле RichText не найдено!"
        Exit Function
    End If

    ' Временный файл для сохранения изображения
    Dim tempImagePath As String
    tempImagePath = "C:\temp\"
    tempImagePath = ExtractImageFromRichText(rtItem, tempImagePath)
    ' Извлекаем изображение из RichText и сохраняем его во временный файл
    If Len(tempImagePath)<4 Then
        Error 1024, "Не удалось извлечь изображение из RichText!"
    End If

    ' Путь для сохранения результата
    Dim outputPath As String, ext As String
    ext=StrRightBack(tempImagePath,{.})
    outputPath = StrLeft(tempImagePath,{.}) &{+text.} &ext

    ' Текст для наложения
    Dim textToAdd As String
    textToAdd = "Hello, World!"

    ' Вызов Java-кода через LS2J
    Dim javaSession As JAVASESSION
    Dim javaCl As JAVACLASS
    Dim javaObj As JAVAOBJECT
    Set javaSession = New JAVASESSION
    Set javaCl = javaSession.GetClass("com.example.ImageTextOverlay")
    Set javaObj = javaCl.Createobject()

    ' Вызов метода для наложения текста
    Call javaObj.OverlayText(tempImagePath, outputPath, textToAdd)

    ' Удаляем старое содержимое RichText-поля
    Call rtItem.Remove

    ' Создаем новое RichText-поле и добавляем в него обработанное изображение
    Set rtItem = doc.CreateRichTextItem("Body") ' Замените "Body" на имя вашего RichText-поля
    Call rtItem.EmbedObject(EMBED_ATTACHMENT, "", outputPath)

    ' Сохраняем документ
    Call doc.Save(True, False)

    ' Очистка временных файлов
    Kill tempImagePath
    Kill outputPath

    Print "Текст успешно наложен на изображение. Результат сохранен в поле RichText документа."
End Function
и агент
Visual Basic:
%REM
    Agent image-tools
    Created Mar 23, 2025 by Mikhail Cholokov/lmike
    Description: Comments for Agent
%END REM
Option Public
Option Declare
Use "image-tools.LS2J"
Sub Initialize
On Error GoTo ErrH
GoTo Begin
ErrH:
    Error Err, "Ошибка в " & GetThreadInfo(1) & ", строка " & CStr(Erl) & ": " & Error$
Begin:
    Dim agent As NotesAgent, ses As New NotesSession, db As NotesDatabase
    Set agent = ses.Currentagent
    Dim doc As NotesDocument
    Set doc=ses.Documentcontext
    TextOverImage doc

End Sub
результат
Посмотреть вложение 79067
что можно дорабатывать:
- оформить java класс в виде builder, для передачи параметров
- использовать анализ имени файла, для правильного определения формата вывода, в классе
- учитывать DPI для масштабирования текста
- сделать конвертор в майм и оттуда забирать изображение (в lotusscript)
- по адресатам, сразу из java, дабы не морочится в ЛС и его переконвертацией
последнее вполне "просто", т.к. у домины есть SMTP и отправка, на сервере, будет через localhost
"единственны момент": для LS2J надо будет javamail либу вкрячивать ;)
 
Последнее редактирование:
Я же написал, что использовал только LS и сторонние DLL. Никакой java!
Файлик выгружается агентом. Конвертируется документ Lotus в xls:
Visual Basic:
sub mime2
    On Error GoTo errh
    Dim ws As New NotesUIWorkspace
    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim col As NotesDocumentCollection
    Dim doc As NotesDocument
    Dim exporter As NotesDXLExporter
    Dim out As String
    Dim filenum As Integer
    Dim p1 As Long
    Dim p2 As Long
    Dim cnt As Integer
    
    Dim rtitem As NotesRichTextItem
    
'    Set doc=ws.CurrentDocument.Document'      current document
    Set db = session.Currentdatabase
    Set col = db.UnprocessedDocuments
    If col.count > 0 Then
        Set doc = col.getfirstdocument
        Call DeleteOut(doc)
    Else
        Exit sub
    End If
    
    'tempdir$=Environ("TEMP")
    tempdir$="C:\dxl"
    tempdir$=tempdir$ & "\"
    'выгружаем xml
    Set exporter = session.CreateDXLExporter
    exporter.Convertnotesbitmapstogif = True
    out = exporter.Export(doc)

    filenum = FreeFile
    Open tempdir$ & "out.xml" For Output As filenum
    Print #filenum, out
    Close filenum
    
    'выгружаем картинки gif
    p1=1
    While p1>0
        p2=0
        p1 = InStr(p1+10, out, "<gif>", 5)
        If p1>0 Then p2 =InStr(p1, out, "</gif>", 5)
        If p2>0 Then
'            Print "Exporting"
            filenum = FreeFile
            filepath$ = tempdir$ & cnt & ".gif"
            Open filepath$ For Output As filenum
            Print #filenum, Base64Decode(Mid$(out, p1+5, p2-p1-5))
            Close filenum
            cnt = cnt + 1
        End If
    Wend
    
    'Notes bytmap
    p1=1
    While p1>0
        p2=0
        p1 = InStr(p1+10, out, "originalformat=notesbytmap>", 5)
        If p1>0 Then p2 =InStr(p1, out, "</gif>", 5)
        If p2>0 Then
'            Print "Exporting"
            filenum = FreeFile
            filepath$ = tempdir$ & cnt & ".gif"
            Open filepath$ For Output As filenum
            Print #filenum, Base64Decode(Mid$(out, p1+30, p2-p1-30))
            Close filenum
            cnt = cnt + 1
        End If

    Wend
    
    'jpeg
    p1=1
    While p1>0
        p2=0
        p1 = InStr(p1+10, out, "<jpeg>", 5)
        If p1>0 Then p2 =InStr(p1, out, "</jpeg>", 5)
        If p2>0 Then
'            Print "Exporting"
            filenum = FreeFile
            filepath$ = tempdir$ & cnt & ".jpg"
            Open filepath$ For Output As filenum
            Print #filenum, Base64Decode(Mid$(out, p1+6, p2-p1-6))
            Close filenum
            cnt = cnt + 1
        End If
    Wend
    
    'jpg
    p1=1
    While p1>0
        p2=0
        p1 = InStr(p1+10, out, "<jpg>", 5)
        If p1>0 Then p2 =InStr(p1, out, "</jpg>", 5)
        If p2>0 Then
'            Print "Exporting"
            filenum = FreeFile
            filepath$ = tempdir$ & cnt & ".jpg"
            Open filepath$ For Output As filenum
            Print #filenum, Base64Decode(Mid$(out, p1+6, p2-p1-6))
            Close filenum
            cnt = cnt + 1
        End If
    Wend
    If Not( doc Is Nothing) Then
        Call DrawTextToImage(filepath$, doc)
    End If
errr:
    Exit Sub
errh:
    MsgBox{Ошибка подпрограммы "mime2" агента "" в строке: } & Erl()
    Resume errr
End Sub
Потом конвертируется изображение их xml в тот формат, что в тегах xml подпрограммой "Base64Code" с параметрами:
Visual Basic:
Function Base64Decode( base64String_o) As String
    Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    Dim dataLength, sOut, groupBegin
    Dim numDataBytes, CharCounter, thysChar, thysData, nGroup, pOut
    Dim Base64String
    Dim i As Long
    Dim s As String
    Dim eval As Variant
    'Remove white spaces, If Any
    'Print "Base64: Removyng Whitespaces #13 "
    base64String = base64String_o
    'Print "Base64: Removyng Whitespaces #13 "
    base64String = Replace(base64String, Chr$(13), "")
    'Print "Base64: Removyng Whitespaces #10 "
    base64String = Replace(base64String, Chr$(10), "")
    'Print "Base64: Removyng Whitespaces #9 "
    base64String = Replace(base64String, Chr$(9), "")
    'Print "Base64: Removyng Whitespaces #32 "
    base64String = Replace(base64String, " ", "")
 
    'The source must consysts From groups With Len of 4 chars
    dataLength = Len(base64String)
    If dataLength Mod 4 <> 0 Then
        MessageBox "Bad string length must be a multiple of 4"
        Exit Function
    End If
 
    'Now decode each group:
    'Print "Base64: Converting... "
    For groupBegin = 1 To dataLength Step 4
        If groupBegin Mod 25 =0 Then Print "Base64: Converting "+Cstr( groupBegin )
            'Each data group encodes up To 3 actual bytes.
            numDataBytes = 3
            nGroup = 0
            For CharCounter = 0 To 3
            'Convert each character into 6 byts of data, And add it To
            'an Integer For temporary storage. If a character Is a =, there
            'Is one fewer data byte. (There can only be a maximum of 2 = In
            'the whole string.)
            thysChar = Mid(base64String, groupBegin + CharCounter, 1)
            If thysChar = "=" Then
                numDataBytes = numDataBytes - 1
                thysData = 0
            Else
                thysData = InStr(Base64, thysChar) - 1
            End If
            If thysData = -1 Then
                MessageBox " Bad character In Base64 string."
                Exit Function
            End If
            nGroup = 64 * nGroup + thysData
        Next
        'Hex splyts the Long To 6 groups With 4 byts
        nGroup = Hex(nGroup)
        'Add leading zeros
        nGroup = String(6 - Len(nGroup), "0") & nGroup
        'Convert the 3 Byte Hex Integer (6 chars) To 3 characters
        pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _
        Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _
        Chr(CByte("&H" & Mid(nGroup, 5, 2)))
        'add numDataBytes characters To out String
        sOut = sOut & Left(pOut, numDataBytes)
    Next
    Base64Decode = sOut
End Function

Дальше другая подпрограмма берет путь к файлу и переменную doc и делает уже надпись:
Visual Basic:
Sub DrawTextToImage(filename As String, doc As NotesDocument)
    On Error GoTo errh
    Dim hdib As Long, txt As String
    
    txt = doc.Getitemvalue("TextToImg")(0)

    res = DIB_LoadFromFilename(filename)

    qqq = DIB_SetViewImage(res)
    Call DIB_SetTextColor(255, 255, 255)
    Call DIB_SetTextHeight(50)
    Call DIB_DrawText(res, txt, 50, 50, -1, -1)
    Call DIB_WriteToFilename(res, filename + ".jpg")
    DIB_Free(res)

errr:
    Exit Sub
errh:
    MsgBox{Ошибка подпрограммы "DrawTextToImage" библиотеки "" агента "" в строке: } & Erl() & Chr(13) & Error()
    Resume errr
End Sub
Использовалась DLL от Twain. Вот декларация:
Visual Basic:
Declare Function DIB_LoadFromFilename Lib "Eztwain3.dll" Alias "DIB_LoadFromFilename" (ByVal sFileName As Lmbcs String) As Long
' Load an image from a file and return its handle.
' The file can be in any format supported by EZTwain Pro.
' If the file is multipage, normally this function loads page 0,
' but a preceding call to DIB_SelectPageToLoad changes that.
' A return of NULL(0) indicates failure, see TWAIN_LastErrorCode
' and related functions for more details.
' If the filename is an empty string (or NULL) the user is prompted
' with a standard file-open dialog.
' EZTwain should read any variant of its supported formats,
' except for PDF: We only claim to support reading images
' from PDFs if they were created by EZTwain Pro.

Declare Function DIB_SetViewImage Lib "Eztwain3.dll" Alias "DIB_SetViewImage" (ByVal hdib As Long) As Long
' If the image viewer is open, change the displayed image to this one.

' The following functions modify the default settings for DIB_DrawText:
Declare Sub DIB_SetTextColor Lib "Eztwain3.dll" Alias "DIB_SetTextColor" (ByVal R As Long, ByVal G As Long, ByVal B As Long)

Declare Sub DIB_SetTextHeight Lib "Eztwain3.dll" Alias "DIB_SetTextHeight" (ByVal nH As Long)
' Set the text character height in pixels.
' If you want to set the text height in physical units (inches)
' multiply the physical height in inches by the DIB_YResolution.
' Note! Some files have resolution=0, which can often be treated as 72dpi

Declare Sub DIB_DrawText Lib "Eztwain3.dll" Alias "DIB_DrawText" (ByVal hdibDst As Long, ByVal sText As Lmbcs String, ByVal leftx As Long, ByVal topy As Long, ByVal w As Long, ByVal h As Long)
' Draw the text string into the DIB inside the given rectangle.
' If w or h is 0, the rectangle is extended to the bottom or right of the DIB.
' Default height is 14 pixels.  Default typeface is "Arial".
' Default color is black (R=G=B=0)
' See the following functions to override the default text settings.


Declare Function DIB_WriteToFilename Lib "Eztwain3.dll" Alias "DIB_WriteToFilename" (ByVal hdib As Long, ByVal sFileName As Lmbcs String) As Long
' Write image to file, using format implied by the filename extension.
'
' If the filename is NULL or points to a null string, the user is
' prompted for the filename and format with a standard Windows
' file-save dialog.
'
' If the final filename has a standard extension (.bmp, .jpg, .jpeg, .tif,
' .tiff, .png, .pdf, .gif, .dcx) then the file is saved in that format.
' Otherwise, the current SaveFormat is used - see TWAIN_SetSaveFormat.
'
' Return values:
'    0  success
'   -1  user cancelled File Save dialog
'   -2  file open error (invalid path or name, or access denied)
'   -3  a) image is invalid (null or invalid DIB handle)
'      b) support for the save format is not configured
'      c) DIB format incompatible with save format e.g. B&W to JPEG.
'   -4  writing data failed, possibly output device is full
'  -5  other unspecified internal error
 
У меня еще в планах: Вставка штампика в первый лист PDF файла таким же методом. И QR code - тоже в лотусовый документ. Пока не исчерпаю возможности LS - буду использовать пока только его, по-возможности без java. Только когда уже приспичит, займусь java.
 
Кстати по декларации Twain - есть полный список экспортируемых функций с описаниями. Если кому-то надо - сигнализируйте. Выложу файлик PDF и LSS.
 
Блин. Вот сидишь, рефакторишь, чтобы абстрактная обработка вместо 30мс была 5мс. А тут бейсик)
А потом удивляемся, чо то тормозит и почемуж проги стали по 100500 метров. Извините, не удержался
 
  • Нравится
Реакции: Gandliar
Блин. Вот сидишь, рефакторишь, чтобы абстрактная обработка вместо 30мс была 5мс. А тут бейсик)
А потом удивляемся, чо то тормозит и почемуж проги стали по 100500 метров. Извините, не удержался
Понимаю. Но тратить время на изучение другого языка, особенно если это требует еще и изучение заплаток - это теже не камильфо! Пишешь тут, понимаешь, на LND 11 версии, а оказывается у нас еще существуют клиенты, работающие на клиенте LN R6! И все коту под хвост....
извините! Тоже не удержался.... "Error loading use or uselsx module: LibName"
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!