class inDesign_Process:
def init(self):
self.in_des_app = self.set_in_des_app()
self.in_des_doc = self.set_in_des_doc()
self.page_ptr = 1 # defines the page we are on
self.lst_flds = []
self.lst_ty = []
self.lst_tx = []
self.lst_by = []
self.lst_bx = []
self.text_start = 4 # where to start text
self.text_end = 49 # when to start a new line
self.in_des_page = self.set_page()
self.geo_bound_ptr = self.reset_geo_bnds()
self.file_name = ""
self.dct_letter_weight = {
"&": 0.75,
"-": 0.6,
"1": 0.6,
"2": 0.6,
"3": 0.6,
"4": 0.65,
"5": 0.65,
"6": 0.7,
"7": 0.7,
"8": 0.65,
"9": 0.65,
"0": 0.65,
",": 0.3,
".": 0.3,
":": 0.3,
" ": 0.2,
"a": 0.6,
"b": 0.6,
"c": 0.57,
"d": 0.6,
"e": 0.65,
"f": 0.36,
"g": 0.65,
"h": 0.65,
"i": 0.3,
"j": 0.3,
"k": 0.6,
"l": 0.3,
"m": 0.9,
"n": 0.65,
"o": 0.65,
"p": 0.65,
"q": 0.65,
"r": 0.375,
"s": 0.6,
"t": 0.375,
"u": 0.6,
"v": 0.6,
"w": 0.85,
"x": 0.6,
"y": 0.6,
"z": 0.6,
"A": 0.75,
"B": 0.75,
"C": 0.75,
"D": 0.75,
"E": 0.75,
"F": 0.6,
"G": 0.75,
"H": 0.75,
"I": 0.375,
"J": 0.6,
"K": 0.75,
"L": 0.6,
"M": 1,
"N": 0.75,
"O": 0.75,
"P": 0.75,
"Q": 0.75,
"R": 0.75,
"S": 0.75,
"T": 0.75,
"U": 0.75,
"V": 0.75,
"W": 1,
"X": 0.75,
"Y": 0.75,
"Z": 0.75,
}
# ===========================================================
# Setup Step 1 Create an App Cursor
# ===========================================================
def set_in_des_app(self):
return win32com.client.Dispatch(
"InDesign.Application.2020", pythoncom.CoInitialize()
)
# ===========================================================
# Setup Step 2 Create Document from App Cursor
# ===========================================================
def set_in_des_doc(self):
return self.in_des_app.Documents.Add()
# ===========================================================
# Setup Step 3 Create Page in Document
# ===========================================================
def set_page(self):
self.geo_bound_ptr = self.reset_geo_bnds() # Fixing Image position maybe
if self.page_ptr != 1:
self.in_des_doc.Pages.Add()
return self.in_des_doc.Pages.Item(self.page_ptr)
# ===========================================================
# Get a Text frame to be used above
# ===========================================================
def get_text_frame(self):
return self.in_des_page.TextFrames.Add()
# ===========================================================
# Get a new image rectangle when adding image (see add_image)
# ===========================================================
def get_image_rectangle(self):
return self.in_des_page.Rectangles.Add()
# ===========================================================
# Move to the next page by
# - incrementing the page pointer
# - set the next inDesign page to write to
# - reset the Geo Boundary pointer to be at top of page
# ===========================================================
def set_next_page(self, imgs_on_page=2):
self.page_ptr += 1
self.in_des_page = self.set_page()
self.geo_bound_ptr = self.reset_geo_bnds()
# ===========================================================
# Set the name of the file to create (full path)
# ===========================================================
def set_filename(self, file_in):
self.file_name = file_in
# ===========================================================
# Save the file from memory onto disk at the file_name
# defined above
# ===========================================================
def save_in_des_file(self):
ret_value = False
directory = os.path.dirname(self.file_name)
try:
# If file path does not exist, create directory
if not os.path.exists(directory):
os.makedirs(directory)
# If file path exist, save the file to the path
if os.path.exists(directory):
self.in_des_doc.Save(self.file_name)
ret_value = True
except Exception as e:
print("Export to inDesign failed: " + str(e))
return ret_value
# ===========================================================
# Close the inDesign Document when done
# ===========================================================
def close_des_file(self):
self.in_des_doc.Close()
# ===========================================================
# ==== =====
# ==== IMAGE FUNCTIONS =====
# ==== =====
# ===========================================================
# ===========================================================
# get the image size to be used to calculate geo boundaries
# when adding an image. image size is a tuple of
# (width, height) (see add_image)
# ===========================================================
def get_image_size(self, img_in):
im = Image.open(img_in)
ret_value = im.size
im.close()
return ret_value
# ===========================================================
# get_image_thumb_size will get the size of the image
# thumbnail. If the image is taller than wider we use
# 400 pixels, if wider than taller we use 900 pixels. This
# will return the size tuple (width, height) of a thumbnail
# that keeps image perspective.
# ===========================================================
def get_image_thumb_size(self, img_in):
img = Image.open(img_in)
img_size = img.size
img_width = img_size[0]
img_height = img_size[1]
if img_width > img_height :
img.thumbnail((900, 900), Image.ANTIALIAS)
else:
img.thumbnail((300, 300), Image.ANTIALIAS)
ret_value = img.size
img.close()
return ret_value
def get_img_per(self,img_size_in,thumb_size_in):
lst_ret_value = []
for item in range(len(thumb_size_in)):
lst_ret_value.append(int(thumb_size_in[item]/img_size_in[item]*100))
return tuple(lst_ret_value)
# ===========================================================
# ==== =====
# ==== GROUPING FUNCTIONALITY =====
# ==== =====
# ===========================================================
# ===========================================================
# start_grouping - resets the list of fields and geoboundaries
# so a new set of textboxes can be grouped together
# ===========================================================
def start_grouping(self):
self.lst_flds = []
self.lst_ty = []
self.lst_tx = []
self.lst_by = []
self.lst_bx = []
# ===========================================================
# add_to_group will take the field passed in, save that in
# the list of fields, get the geoboundary of the textbox and
# save each item in its appropriate list (top y in ty, etc)
# ===========================================================
def add_to_group(self,fld_in):
self.lst_flds.append(fld_in)
geo_bnd = fld_in.GeometricBounds
self.lst_ty.append(geo_bnd[0])
self.lst_tx.append(geo_bnd[1])
self.lst_by.append(geo_bnd[2])
self.lst_bx.append(geo_bnd[3])
# ===========================================================
# end_grouping will take all the textframes stored and group
# them together.
# ===========================================================
def end_grouping(self):
lst_items = self.lst_flds[:]
group_ret_value = lst_items[0]
for item in range(1,len(lst_items)):
lst_items[item].PreviousTextFrame = lst_items[item-1]
for item in range(1,len(lst_items)):
lst_items[item].Delete()
self.lst_ty.sort()
self.lst_tx.sort()
self.lst_by.sort(reverse=True)
self.lst_bx.sort(reverse=True)
top_y = int(self.lst_ty[0])
top_x = int(self.lst_tx[0])
bot_y = int(self.lst_by[0])
bot_x = int(self.lst_bx[0])
lst_group_bound = ["0","0","0","0"]
lst_group_bound = self.set_top_y(lst_group_bound,top_y)
lst_group_bound = self.set_top_x(lst_group_bound,top_x)
lst_group_bound = self.set_bot_y(lst_group_bound,bot_y)
lst_group_bound = self.set_bot_x(lst_group_bound,bot_x)
group_ret_value.NextTextFrame = None
group_ret_value.Fit(FitOptions.FRAME_TO_CONTENT.value)
group_ret_value.GeometricBounds = lst_group_bound
group_ret_value.TextFramePreferences.VerticalJustification = (
TextVJust.CENTER_ALIGN.value
)
self.geo_bound_ptr = lst_group_bound
# print(f"after group :{self.geo_bound_ptr}")
self.geo_bnds_next_line() # start on new line
# print(f"after group next line:{self.geo_bound_ptr}")
# ===========================================================
# ==== =====
# ==== GEOBOUND FUNCTIONALITY =====
# ==== =====
# ===========================================================
# ===========================================================
# Geometric Bounds Functions
#
# Geometric Bounds [ty, tx, by, bx] or (y1, x1, y2, x2)
# maps the top left the bottom right of a box
# NOTE: y is first, by using a set of wrapper functions
# that will be something that the user won't need to remember
# ===========================================================
# ===========================================================
# Reset Geo Boundary - when starting a new page, the
# geo boundary should be reset to the top of the page
# ===========================================================
def reset_geo_bnds(self):
ret_value = ["1", "2", "3", "4"] # geo bound placeholders
ret_value = self.set_top_x(ret_value, self.text_start)
ret_value = self.set_top_y(ret_value, self.text_start)
ret_value = self.set_bot_x(ret_value, self.text_start)
ret_value = self.set_bot_y(ret_value, self.text_start + 1)
return ret_value
# ===========================================================
# setting ty of [ty, tx, by, bx]
# val_in is an integer (ex 4)
# we make 4p0 as ty
# ===========================================================
def set_top_y(self, geo_bnd_in, val_in):
ret_value = geo_bnd_in[:]
top_x_adj = f"{val_in}p0"
ret_value[0] = top_x_adj
return ret_value
# ===========================================================
# setting tx of [ty, tx, by, bx]
# val_in is an integer (ex 4)
# we make 4p0 as tx
# ===========================================================
def set_top_x(self, geo_bnd_in, val_in):
ret_value = geo_bnd_in[:]
top_y_adj = f"{val_in}p0"
ret_value[1] = top_y_adj
return ret_value
# ===========================================================
# setting by of [ty, tx, by, bx]
# val_in is an integer (ex 4)
# we make 4p0 as by
# ===========================================================
def set_bot_y(self, geo_bnd_in, val_in):
ret_value = geo_bnd_in[:]
bot_x_adj = f"{val_in}p0"
ret_value[2] = bot_x_adj
return ret_value
# ===========================================================
# setting bx of [ty, tx, by, bx]
# val_in is an integer (ex 4)
# we make 4p0 as bx
# ===========================================================
def set_bot_x(self, geo_bnd_in, val_in):
ret_value = geo_bnd_in[:]
bot_y_adj = f"{val_in}p0"
ret_value[3] = bot_y_adj
return ret_value
# ===========================================================
# getting ty of [ty, tx, by, bx]
# removing the p0 from ty (ex 4p0)
# returning the integer 4
# ===========================================================
def get_top_y(self, geo_bnd_in):
return int(geo_bnd_in[0].split("p")[0])
# ===========================================================
# getting tx of [ty, tx, by, bx]
# removing the p0 from tx (ex 4p0)
# returning the integer 4
# ===========================================================
def get_top_x(self, geo_bnd_in):
return int(geo_bnd_in[1].split("p")[0])
# ===========================================================
# getting by of [ty, tx, by, bx]
# removing the p0 from by (ex 4p0)
# returning the integer 4
# ===========================================================
def get_bot_y(self, geo_bnd_in):
return int(geo_bnd_in[2].split("p")[0])
# ===========================================================
# getting bx of [ty, tx, by, bx]
# removing the p0 from bx (ex 4p0)
# returning the integer 4
# ===========================================================
def get_bot_x(self, geo_bnd_in):
return int(geo_bnd_in[3].split("p")[0])
# ===========================================================
# Geometric Boundaries Next Line
#
# This function will go through setting the geo boundaries
# to go to the next line.
# - Move the new top y to bot y
# - Add 1 to bot y
# - Set botx and topx to text_start (defined in init)
# - Return the new Geo Boundary
# ===========================================================
def geo_bnds_next_line(self):
next_geo = self.geo_bound_ptr[:]
# set top equal to bottom
bot_y_val = self.get_bot_y(next_geo)
next_geo = self.set_top_y(next_geo, bot_y_val)
bot_y_val += 1 # add 1
next_geo = self.set_bot_y(next_geo, bot_y_val)
# set to self.text_start+2 if you want to indent
next_geo = self.set_top_x(next_geo, self.text_start)
next_geo = self.set_bot_x(next_geo, self.text_start)
self.geo_bound_ptr = next_geo
# ===========================================================
# Add Image PUBLIC FACING FUNCTION
#
# This function will go through the process of adding an
# image to the page
# - Check to see if this is a new page if not move down
# 4 lines
# - Get a new image rectangle
# - Get the size of the image (length,height)
# - Get the image rectange geo boundary size (rec_geo_bnd)
# - Set the image size to 30%
# - readjust the geo boundary for text under image
# ===========================================================
def add_image(self, img_in):
my_frame = self.get_image_rectangle()
img_size = self.get_image_size(img_in)
thumb_size = self.get_image_thumb_size(img_in)
#print(f"thumb_size :{thumb_size}")
rec_geo_bnd = self.geo_get_image_spacing(thumb_size)
rec_geo_bnd = self.image_geo_adjust(rec_geo_bnd,thumb_size)
#print(f"rec_geo_bnd :{rec_geo_bnd}")
rec_geo_bnd = self.geo_bnd_page_adj(rec_geo_bnd) # adjust for page
my_frame.GeometricBounds = rec_geo_bnd
my_graphic_list = my_frame.Place(img_in)
horiz_per,vert_per = self.get_img_per(img_size,thumb_size)
#print(f"horiz_per:{horiz_per} vert_per: {vert_per}")
my_frame.HorizontalScale = horiz_per
my_frame.VerticalScale = vert_per
my_object_style = self.in_des_doc.ObjectStyles.Add()
my_object_style.EnableStroke = True
my_object_style.StrokeWeight = 3
my_object_style.StrokeType = self.in_des_doc.StrokeStyles.Item("Solid")
my_object_style.StrokeColor = self.in_des_doc.Colors.Item("Black")
my_frame.ApplyObjectStyle(my_object_style, True)
my_frame.Fit(FitOptions.FRAME_TO_CONTENT.value)
# ===================================================
# if we use the geo bounds for images, they move
# the text too far down, we need to adjust the
# geo boundaries to more "text like" before
# updating geo_bound_ptr
# ===================================================
self.geo_bound_ptr = self.text_geo_adjust(rec_geo_bnd, thumb_size)
self.geo_bnds_next_line() # start on newline for text
def px_to_geo(self,val_in):
return int(val_in/35)
def image_geo_adjust(self, geo_bnd_in, thumb_size_in):
ret_value = geo_bnd_in[:]
bot_y = self.get_bot_y(ret_value)
delta_y = self.px_to_geo(thumb_size_in[1])
bot_y = bot_y + delta_y
ret_value = self.set_bot_y(ret_value,bot_y)
return ret_value
def geo_get_image_spacing(self, thumb_size_in):
ret_value = self.geo_bound_ptr[:] # start where text left off
#print(f"1 image_spacing :{ret_value}")
top_x = self.get_top_x(ret_value)
bot_x = self.get_bot_x(ret_value)
top_y = self.get_top_y(ret_value)
bot_y = self.get_bot_y(ret_value)
if top_x < 6:
top_x = 6
if top_y < 6:
top_y = 6
else:
thumb_height = thumb_size_in[1]
delta_y = self.px_to_geo(thumb_height)
top_y = top_y + delta_y
bot_y = bot_y + delta_y
thumb_width = thumb_size_in[0]
geo_wdth = self.px_to_geo(thumb_width)
delta_x = int((49 - geo_wdth)/2)
top_x = top_x + delta_x
bot_x = bot_x + delta_x
ret_value = self.set_top_x(ret_value,top_x)
ret_value = self.set_bot_x(ret_value,bot_x)
ret_value = self.set_top_y(ret_value,top_y)
ret_value = self.set_bot_y(ret_value,bot_y)
#print(f"2 image_spacing :{ret_value}")
return ret_value
def text_geo_adjust(self, geo_bnd_in, thumb_size_in):
ret_value = geo_bnd_in[:]
top_y = self.get_top_y(ret_value)
delta_y = self.px_to_geo(thumb_size_in[1])
top_y = top_y + delta_y
ret_value = self.set_top_y(ret_value,top_y)
return ret_value
# ===========================================================
# Geo Boundary Page Adjustment.
#
# Odd # pages except 1 (ex 3,5,7) need to have the top and
# bottom x moved over to appear on the right page. 55 seems
# to be a good number.
# ===========================================================
def geo_bnd_pg_adj(self, geo_bnd_in):
ret_value = geo_bnd_in[:]
if self.page_ptr % 2 == 1 and self.page_ptr > 1:
top_x = self.get_top_x(ret_value)
bot_x = self.get_bot_x(ret_value)
ret_value = self.set_top_x(ret_value, top_x + 45)
ret_value = self.set_bot_x(ret_value, bot_x + 45)
return ret_value
# ===========================================================
# Text Functions Public Facing Functions
# ===========================================================
# ===========================================================
# Wrapper to get the next line
# ===========================================================
def set_next_line(self):
self.geo_bnds_next_line()
# ===========================================================
# Add text defined as a label
# - Text is bolded
# - Text is right aligned
# ===========================================================
def add_label(self, word_in):
self.geo_bnds_right(word_in)
label_frame = self.get_text_frame()
geo_bound_adj = self.geo_bnd_page_adj(self.geo_bound_ptr)
label_frame.TextFramePreferences.VerticalJustification = (
TextVJust.CENTER_ALIGN.value
)
label_frame.GeometricBounds = geo_bound_adj
label_frame.texts[0].pointSize = "12pt"
label_frame.ParentStory.AppliedFont = "Arial"
label_frame.ParentStory.FontStyle = "Bold"
label_frame.ParentStory.Justification = Justify.RIGHT_ALIGN.value # Right Align
label_frame.Contents = word_in
self.add_to_group(label_frame)
# ===========================================================
# Add text defined as plain text
# - if the text is going over the end of the line go to the
# next line
# ===========================================================
def add_text(self, word_in, split_text=False):
word_weight = int(self.get_word_points(word_in))
# print(f"word_in :{word_in}")
self.geo_bnds_right(word_in)
text_frame = self.get_text_frame()
geo_bound_adj = self.geo_bound_ptr # don't adjust till afterwards
if word_weight+self.text_start > self.text_end:
bot_y = self.get_bot_y(geo_bound_adj)
geo_bound_adj = self.set_top_x(geo_bound_adj, self.text_start)
geo_bound_adj = self.set_bot_x(geo_bound_adj, self.text_end - 1)
if (word_weight / self.text_end).is_integer():
bot_y_delta = int(word_weight / self.text_end)
else:
bot_y_delta = int(word_weight / self.text_end) + 2
geo_bound_adj = self.set_bot_y(geo_bound_adj, bot_y + bot_y_delta + 1)
self.geo_bound_ptr = self.set_bot_y(
self.geo_bound_ptr, bot_y + bot_y_delta + 1
) # set geo pointer's bottom y
geo_bound_adj = self.geo_bnd_page_adj(geo_bound_adj) # see if moving after sizing will put on proper page
# print(f"geo_bound_adj after :{geo_bound_adj}")
text_frame.TextFramePreferences.VerticalJustification = (
TextVJust.CENTER_ALIGN.value
)
text_frame.GeometricBounds = geo_bound_adj
text_frame.texts[0].pointSize = "12pt"
text_frame.ParentStory.AppliedFont = "Arial"
text_frame.Contents = word_in + " "
self.add_to_group(text_frame)
# ===========================================================
# Add text defined as a title
# - text is bolded
# ===========================================================
def add_title(self, word_in):
word_weight = int(self.get_word_points(word_in))
self.geo_bnds_right(word_in)
title_frame = self.get_text_frame()
geo_bound_adj = self.geo_bnd_page_adj(self.geo_bound_ptr)
geo_bound_adj = self.geo_bound_ptr # don't adjust till afterwards
if word_weight+self.text_start > self.text_end:
bot_y = self.get_bot_y(geo_bound_adj)
geo_bound_adj = self.set_top_x(geo_bound_adj, self.text_start)
geo_bound_adj = self.set_bot_x(geo_bound_adj, self.text_end - 1)
if (word_weight / self.text_end).is_integer():
bot_y_delta = int(word_weight / self.text_end)
else:
bot_y_delta = int(word_weight / self.text_end) + 2
geo_bound_adj = self.set_bot_y(geo_bound_adj, bot_y + bot_y_delta + 1)
self.geo_bound_ptr = self.set_bot_y(
self.geo_bound_ptr, bot_y + bot_y_delta + 1
) # set geo pointer's bottom y
geo_bound_adj = self.geo_bnd_page_adj(geo_bound_adj) # see if moving after sizing will put on proper page
title_frame.TextFramePreferences.VerticalJustification = (
TextVJust.CENTER_ALIGN.value
)
title_frame.GeometricBounds = geo_bound_adj
title_frame.texts[0].pointSize = "12pt"
title_frame.ParentStory.AppliedFont = "Arial"
title_frame.ParentStory.FontStyle = "Bold"
title_frame.Contents = word_in + " "
self.add_to_group(title_frame)
# ===========================================================
# Geo Boundary right
#
# Find out the spacing for the words in the textbox and make
# the textbox the proper size. Set the Geo boundary
# accordingly.
# ===========================================================
def geo_bnds_right(self, word_in):
new_line_pos = self.geo_get_word_spacing(word_in)
if new_line_pos >= self.text_end:
self.geo_bnds_next_line()
new_line_pos = self.geo_get_word_spacing(word_in)
# ===========================================================
# Get Geo Boundary word spacing
#
# This function will take the current geo boundary and
# add the amount of space needed for the text to store in
# this textbox
# ===========================================================
def geo_get_word_spacing(self, word_in):
ret_value = self.geo_bound_ptr[:]
top_x_val = self.get_top_x(ret_value)
bot_x_val = self.get_bot_x(ret_value)
ret_value = self.set_top_x(ret_value, bot_x_val)
right_append = self.get_word_points(word_in) # the space the word needs
new_line_pos = int(right_append) + bot_x_val + 1
ret_value = self.set_bot_x(ret_value, new_line_pos)
self.geo_bound_ptr = ret_value
return new_line_pos
# ===========================================================
# get word points
#
# Will get the weighted values of letters defined in
# dct_letter_weight. after a cummulative number is reached
# that's passed back and the integer value is used.
# ===========================================================
def get_word_points(self, word_in):
ret_value = 0.0
for letter in word_in:
if letter in self.dct_letter_weight.keys():
ret_value += self.dct_letter_weight[letter]
return ret_value
# ===========================================================
# Geo Boundary Page Adjustment.
#
# Odd # pages except 1 (ex 3,5,7) need to have the top and
# bottom x moved over to appear on the right page. 51 seems
# to be a good number for text
# ===========================================================
def geo_bnd_page_adj(self, geo_bnd_in):
ret_value = geo_bnd_in[:]
if self.page_ptr % 2 == 1 and self.page_ptr > 1:
top_x = self.get_top_x(ret_value)
bot_x = self.get_bot_x(ret_value)
ret_value = self.set_top_x(ret_value, top_x + 51)
ret_value = self.set_bot_x(ret_value, bot_x + 51)
return ret_value
# TEST INDESIGN CLASS
#
# THIS PROGRAM IS FREE SOFTWARE. IT COMES WITHOUT ANY WARRANTY, TO
# THE EXTENT PERMITTED BY APPLICABLE LAW. YOU CAN REDISTRIBUTE IT
# AND/OR MODIFY IT UNDER SIMILAR TERMS. THIS CODE IS DISTRIBUTED "AS IS".
# THE USER ACCEPTS ALL RESPONSIBILITIES
#
# This class will put an image above, add text below, and group all the
# text into one textframe at the end. Most of my calculations were eye-
# balling the output. If anyone has a more accurate conversion (like
# pixels to geo boundary units), please feel free to modify and repost.
#
# I use the general space of the characters in Arial font at 12 point
# to calculate the weight (width) of a set of text. Again, the weight
# of each character was what I saw.
#
# WHAT YOU NEED TO DO TO RUN THIS EXAMPLE
#
# You need to add any images below. I use a string var
# to define wide and long images.
# You also need to put in the full path of the output file you want
# to generate.
# The images I put I use a % by calculating the thumbnail and using
# that for calculations.
#
# THINGS I FOUND
#
# One weird thing I found is that odd pages over 1, the position
# is actually a full page over. geo_bnd_page_adj takes care of that
#
# The GeoBoundary Group of coordinates are in the order y,x and not
# x,y the way I've always known coordinates. That's why I added
# gets and sets for top_x,top_y,bot_x and bot_y, to avoid confusing
# myself.
#
# InDesign comes up with a new COM object to address which seems to
# corrispond with the year of the InDesign release. I have InDesign
# 2020 so my call in set_in_des_app is to "InDesign.Application.2020".
# Change the year suffix to match the version of InDesign you're working
# with. In the past it seems the same COM, just rebundled. Hopefully,
# they'll keep it similar in future releases.
#
# ========================================================================
lst_words = ["this is an","unscientific","way:","to","see","how:","words","go","together:", "adding more", "stuff", "on", "the", "end"]
img_long = 'C:\\full\\path\\to\\long\\image" #<====put your images here
img_wide = 'C:\\full\\path\\to\\wide\\image" #<====put your images here
img_small = 'C:\\full\\path\\to\\small\\image" #<====put your images here
# 2 items on a page
# long, wide
#lst_imgs = [img_long,img_wide]
# wide, long
#lst_imgs = [img_wide, img_long]
# long, long
#lst_imgs = [img_long, img_long]
# wide, wide
#lst_imgs = [img_wide,img_wide]
#small, big
#lst_imgs = [img_small,img_wide]
# 3 items on a page
# long, wide, long
#lst_imgs = [img_long,img_wide,img_long]
# wide, long, wide
#lst_imgs = [img_wide, img_long, img_wide]
# long, long, long
#lst_imgs = [img_long, img_long, img_long]
# wide, wide, wide
#lst_imgs = [img_wide,img_wide, img_wide]
in_des_doc = inDesign_Process()
for img_item in lst_imgs:
in_des_doc.add_image(img_item)
in_des_doc.start_grouping() # start grouping text frames together under image
for word in lst_words:
if "this is" in word:
id_test = in_des_doc.add_title(word)
elif ":" in word:
in_des_doc.add_label(word)
else:
in_des_doc.add_text(word)
in_des_doc.end_grouping() # merge text frames
#in_des_doc.set_next_page() # Will go to the next page
in_des_doc.set_filename(r'C:\full\path\to\output\filename.indd') #<=====put your full path and filename to generate here
if in_des_doc.save_in_des_file():
print("SUCCESS!!!!")
else:
print("FAIL!!!!!!")
in_des_doc.close_des_file()
===========================================================
indesign-class.py
Created: 07 JUNE 2022
author = 'Scott H' version = '1.0'
""" This is a class to generate an InDesign document """
""" Instructions are below in the main """
===========================================================
import win32com.client import os from win32com.client import Dispatch from enum import Enum from PIL import Image import pythoncom
class TextWrapOptions(Enum): idBoundingBoxTextWrap = 1651729523 # from enum idTextWrapModes idContour = 1835233134 # from enum idTextWrapModes idJumpObjectTextWrap = 1650552420 # from enum idTextWrapModes idNextColumnTextWrap = 1853384306 # from enum idTextWrapModes idNone = 1852796517 # from enum idTextWrapModes
===========================================================
Values to use when definining text justification in a
textframe
===========================================================
class Justify(Enum): AWAY_FROM_BINDING_SIDE = 1633772147 # from idJustification CENTER_ALIGN = 1667591796 # from idJustification CENTER_JUSTIFIED = 1667920756 # from idJustification FULLY_JUSTIFIED = 1718971500 # from idJustification LEFT_ALIGN = 1818584692 # from idJustification LEFT_JUSTIFIED = 1818915700 # from idJustification RIGHT_ALIGN = 1919379572 # from idJustification RIGHT_JUSTIFIED = 1919578996 # from idJustification TO_BINDING_SIDE = 1630691955 # from idJustification
===========================================================
Values to use when defining an image frame fit options
===========================================================
class FitOptions(Enum): APPLY_FRAME_FITTING_OPTIONS = 1634100847 # from enum idFitOptions CENTER_CONTENT = 1667591779 # from enum idFitOptions CONTENT_AWARE_FIT = 1667327593 # from enum idFitOptions CONTENT_TO_FRAME = 1668575078 # from enum idFitOptions FILL_PROPORTIONALLY = 1718185072 # from enum idFitOptions FRAME_TO_CONTENT = 1718906723 # from enum idFitOptions PROPORTIONALLY = 1668247152 # from enum idFitOptions
===========================================================
Values to use when we vertically justify text
===========================================================
class TextVJust(Enum): BOTTOM_ALIGN = 1651471469 # from enum idVerticalJustification CENTER_ALIGN = 1667591796 # from enum idVerticalJustification JUSTIFY_ALIGN = 1785951334 # from enum idVerticalJustification TOP_ALIGN = 1953460256 # from enum idVerticalJustification
========================================================================
========================================================================
====== InDesign Process ======
====== ======
====== This class will generate an inDesign Document. ======
====== Steps to creating an inDesign Document: ======
====== ======
====== 1 - Create an app cursor by attaching to C library ======
====== 2 - Use app cursor to create a in memory document ======
====== 3 - Set the Page (starting with page 1) ======
====== ======
========================================================================
========================================================================
class inDesign_Process: def init(self): self.in_des_app = self.set_in_des_app() self.in_des_doc = self.set_in_des_doc() self.page_ptr = 1 # defines the page we are on self.lst_flds = [] self.lst_ty = [] self.lst_tx = [] self.lst_by = [] self.lst_bx = []
if name == 'main':
========================================================================