Параметр blank
используется в валидации формы, а null
используется при записи в базу данных.
Таким образом, вы можете добавить null=True
в это поле.
EDIT: продолжить комментарий
Рассмотрение двух шагов при сохранении объекта:
blank
) 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
, которая запутывает (и может вызывать ошибки).
Чтобы подсчитать абзацы содержимого в буфере обмена, используя объектную модель 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
Вдохновленный комментарием Синди Мейстер (см. Выше), я нашел следующее решение (которое включает в себя сначала создание нового объекта документа 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 ...