H O M E

Jonathan Cooper
Manager of Information,
Art Gallery of New South Wales, Sydney, AUSTRALIA

Writing About HyperCard

Exporting from HyperCard

Originally published in MACinations (Club Mac, Sydney, Australia)

While having text broken up into cards and fields in HyperCard makes information easier to find and manipulate, there are times when you want to get pieces of text, or all the text from one or more cards, into one file for editing and/or printing with a word processor. Even if you have enough memory to run HyperCard plus your favourite word processor together, having to select, copy, switch applications, click, paste and switch back over and over again can get very tedious. HyperTalk has four commands that allow a stack to exchange data with a text file automatically (1), but having to write a custom handler every time you want to export text just isn't practical.

Robert Murray of the Massachussets Institute of Technology Media Lab has created a HyperCard 2.x stack called Import/Export Tools which enables you to transfer data from text file to stack, from stack to text file and even stack to stack. To allow for any stack structure (including multiple backgrounds) and for user preferences as to which fields are to be exported and in what order, the stack is by necessity fairly complex. If the amount and/or complexity of information is high however, then this is the way to go. If, on the other hand, you need to export data 'on the fly', without structuring beforehand, another solution might be more suitable.

The first thing that we need to do is set up a link between HyperCard and a text file (either freshly created or already existing) so that we can export all our text to the one place. Two message handlers will do the trick:

on createFile
   global textFile
   -- global variables keep their contents 
   -- as long as HyperCard is running, which
   -- is why we declare file's path-name as 
   -- a global variable
 
   ask file "Save as:" with short name of this stack &&  "Text"
   if it is empty then exit createFile
   -- (If "Cancel" is clicked 'it' is empty:
   -- allows user to back out)
   put it into textFile
 
   open file textFile
   -- (This is where the file is created)
 
   close file textFile
   -- (For safety; other handlers will open
   -- it again when necessary)
 end createFile
 
 on openFile
   global textFile
   answer file "Select a text file to export to:" of type "TEXT"
   if it is empty then exit openFile
   put it into textFile
 end openFile

Secondly we need to create handlers to actually do the exporting. However, it is important to keep adding the text we export to the declared file. Normally when you tell HyperCard to open a file and then write text to it, the text replaces whatever is already there. The solution is to read from the file until the end and then write to it. The data gets read into the special global variable 'it' but we don't actually need to do anything with it; it is simply to move a pointer from the beginning to the end of the file. This pointer is like a bookmark; it is the computer's way of keeping track of where it is up to, where to write (or read) the next bit of text. The default is always the beginning of the file. (2)

The following five lines are the basis of what is required. (In an actual script, we would substitute an actual expression for the place-holder <data> .)

  ...
  global textFile
  open file textFile
  read from file textFile until empty
  write <data> to file textFile
  close file textFile
  ...

Thirdly, we must create handlers to collect text ready for exporting. The most basic (exporting whatever text is selected) is also the easiest...

  get the selection -- i.e. put the selection into the variable 'it'
  -- later we will write 'it' to file textFile

Next, all the text from the current card...

  put empty into soFar
  -- (soFar is a local variable for
  -- storing text, ready for exporting)

  repeat with i=1 to the number of card fields
    put card field i & return & return after soFar
    -- (Put blank line after each field)
  end repeat

  repeat with i=1 to the number of bkgnd fields
    put bkgnd field i & return & return after soFar
  end repeat

  -- we will later write soFar to file textFile

Then, the same as above but from a range of cards (using an repeat loop with the repeat loop listed above nested inside it).

Also, to help make the resultant text file easier to read, we should provide ways to separate the slabs of text we export. A blank line (or extra return), and possibly a series of 'bullets' should do the trick.

OK, we have enough to create the required handlers. The trouble is, must we remember their names so that we can type them into the message box when required? Some people have no problem with this, but it is not really in keeping with the philosophy of Macintosh, let alone HyperCard. (Also, typing return or enter-to 'enter' the command-will deselect any text.) Why not create a menu, since HyperCard 2.x makes it so easy? (No messy XCMDs!)

The recommended (but not the only) way to do it is to create a menu-creating handler (say "ExportMenu") which calls two functions createExportMenuItems and createExportMenuMsgs:

on ExportMenu
  if there is a menu "Export"
  then exit ExportMenu
  -- (Don't want to duplicate)
  create menu "Export"
  put createExportMenuItems() into menu "Export" with menuMsg createExportMenuMsgs()
end ExportMenu

function createExportMenuItems
  global textFile
  -- (The name of the export file,
  -- stored as a global variable)
  return "New File..." & return &

  ...
  -- other menu item names listed
  -- here, separated by returns
end createExportMenuItems

function createExportMenuMsgs
  return "createFile" & return &
  ...
  -- other menu messages listed
  -- here, separated by returns
end createExportMenuMsgs

The reason for doing it in three handlers rather than one is to make it easier to read, and edit if necessary. Each menu item now has its own command (or "menuMessage") that can be trapped by a message handler that we create. E.g. Selecting the first menu item ("New File...") sends the message "createFile" which we can trap with an "on createFile" handler.

Two more things are needed to make our technique functional: a way of indicating whether or not field names are to be included when each card's text is exported and a way to open the text file when all the exporting is complete.

The former could be handled by a checkable menu item "Include Field Names"with the menuMessage "toggleFieldNames":

on toggleFieldNames
  set checkMark of menuItem "Include Field Names" of menu "Export"

  to not checkMark of menuItem "Include Field Names" of menu "Export"
end toggleFieldNames

(Any export handlers would need to check the checkmark of menuItem "Include Field Names" before collecting any text.)

The latter is as simple as:

  open textFile with "Microsoft Word" -- or whatever

 

See these techniques in action

To see the techniques described above in a working stack, download my stack Export Menu.

_____

1. ...

2. Starting with HyperCard 2.2, you can write:
write to file textFile at end
to avoid having to read the entire file first.

Writing About HyperCard
Top