VBA в Word: Как подсчитать количество абзацев в содержимом буфера обмена

Параметр blank используется в валидации формы, а null используется при записи в базу данных.

Таким образом, вы можете добавить null=True в это поле.

EDIT: продолжить комментарий

Рассмотрение двух шагов при сохранении объекта:

  1. Validator (контролируется blank)
  2. Ограничение базы данных ( null)

Для опции default возьмите IntegerField, например, default=5, blank=True, null=False, pass (1), даже если вы не присвоили значение (имеющее blank=True), передать (2), поскольку оно имеет значение по умолчанию (5) и записывает 5 вместо None в DB. blank=True, null=False, которые проходят (1), но не (2), потому что он пытается записать None в DB.

Таким образом, если вы хотите сделать поле необязательным, используйте либо default=SOMETHING, blank=True, null=False, либо blank=True, null=True.

Другим исключением является строковое поле, например CharField. Предполагается, что использовать только blank=True, оставив null=False позади. Это делает поле строкой (> = 1 char (s)) или пустую строку ('', с len () == 0) и никогда None.

Причина в том, что когда установлено null=True, будет существовать два возможных значения для состояния «unset»: пустая строка и None, которая запутывает (и может вызывать ошибки).

1
задан Cindy Meister 23 February 2019 в 18:52
поделиться

2 ответа

Чтобы подсчитать абзацы содержимого в буфере обмена, используя объектную модель Word, сначала необходимо поместить это содержимое в документ Word. Буфер обмена не является частью Word и не «понимает» синтаксис Word.

Хотя это можно сделать, используйте Selection и Activate, но вместо этого более эффективно и менее «раздражает» работать с объектами Word. В этом случае объявите объект Document и установите добавляемый к нему документ. Тогда можно всегда использовать эту объектную переменную - не нужно ее активировать, не нужно использовать Documents(index) для адресации этого документа.

Кроме того, я бы хотел поместить эти шаги в отдельную процедуру, которая возвращает количество абзацев. Как правило, это облегчает чтение и поддержку кода.

Например:

Function InsertAndProcessMultipleParagraphs() As Long

'Declarations    
    Dim MyData As MSForms.DataObject
    Dim intNumPara As Integer
    Dim objDoc as Word.Document
    Dim rng as Word.Range

'Fill them objects
'?Probably not needed for this approach?
'    Set MyData = New MSForms.DataObject
'    MyData.GetFromClipboard

    Set objDoc = Application.Documents.Add
    objDoc.ActiveWindow.Visible = False

'Put clipboard contents into the new document object
   Set rng = objDoc.Content
   rng.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Read out paragraph number in that document    
    intNumPara = objDoc.Paragraphs.Count

'Close that document (without nasty questions)     
    objDoc.Close SaveChanges:=wdDoNotSaveChanges   
    InsertAndProcessMultipleParagraphs = intNumPara
End Function

Sub MacroThatUsesTheInfo
   Dim intNumPara as Long

   intNumPara = InsertAndProcessMultipleParagraphs

'Paste the Clipboard content into target document at current cursor position 
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Expand selection to cover all the paragraphs inserted    
    Selection.MoveUp Unit:=wdParagraph, Count:=intNumPara, Extend:=wdExtend

'Do something nice and useful with these paragraphs 
    Application.Run MacroName:="Normal.MyMacros.Do-someting-nice-and-useful"

End Sub
0
ответ дан Cindy Meister 23 February 2019 в 18:52
поделиться

Вдохновленный комментарием Синди Мейстер (см. Выше), я нашел следующее решение (которое включает в себя сначала создание нового объекта документа Word, затем вставку в него содержимого буфера обмена, а затем считывание номера его абзаца):

Sub InsertAndProcessMultipleParagraphs()

'Declarations    
    Dim MyData As MSForms.DataObject
    Dim intNumPara As Integer
    Dim objDoc

'Fill them objects
    Set MyData = New MSForms.DataObject
    MyData.GetFromClipboard

    Set objDoc = Application.Documents.Add
    objDoc.ActiveWindow.Visible = False

'Put clipboard contents into the new document object
    Documents(objDoc).Activate
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Read out paragraph number in that document    
    intNumPara = Documents(objDoc).Paragraphs.Count

'Close that document (without nasty questions)     
    Documents(objDoc).Close SaveChanges:=wdDoNotSaveChanges

'By some miracle we should now be back in Word's original target window... 
'Tests show that in practice this is the case. 

'Paste the Clipboard content into target document at current cursor position 
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Expand selection to cover all the paragraphs inserted    
    Selection.MoveUp Unit:=wdParagraph, Count:=intNumPara, Extend:=wdExtend

'Do somethign nice and useful with these paragraphs 
    Application.Run MacroName:="Normal.MyMacros.Do-someting-nice-and-useful"

End Sub

Однако я немного разочарован тем, что мне приходится качать такой большой и тяжелый молоток, как создание целого нового объекта документа в Word только для того, чтобы сосчитать эти абзацы. Создание документа, переключение на него, вставка чего-либо, подсчет абзацев, закрытие документа ... это много операций для очень простой вещи. Нет ли еще доступного более легкого объекта, который мог бы взять содержимое буфера обмена и чей номер абзаца я мог бы тогда прочитать?

Возможно, я попробую и другой метод: подсчитать метки абзаца (возврат каретки или около того) в строке, которую можно извлечь из объекта MyData ...

0
ответ дан marc_s 23 February 2019 в 18:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: