วันอังคารที่ 18 มกราคม พ.ศ. 2554

การเขียนวิทยานิพนธ์ ม.ข. ด้วย LaTeX - สร้างสารบัญ

ข้อกำหนดหนึ่งของวิทยานิพนธ์บัณฑิตศึกษา มหาวิทยาลัยขอนแก่นคือสารบัญ
ข้อกำหนดคือ
  1. สารบัญ และส่วนประกอบอื่น ๆ เช่น กิตติกรรมประกาศ มีศักดิ์ศรีเทียบเท่าบท ดังนั้นหัวข้อของสารบัญจึงใช้หัวข้อของบท แต่ไม่ต้องมีเลขบท คือเป็นตัวอักษรแบบตัวหนาขนาด 18 พอยต์ (Bold 18 points) อยู่กึ่งกลางหน้ากระดาษ
  2. หากสารบัญมีมากกว่าหนึ่งหน้า หน้าต่อ ๆ ไปของสารบัญจะต้องขึ้นหัวข้อว่า "สารบัญ (ต่อ)" ด้วยอักษรตัวหนาขนาด 18 พอยต์เช่นเดียวกัน (ข้อนี้ไม่มีคำสั่งเป็นลายลักษณ์อักษร แต่ตัวอย่างที่มีให้เป็นแบบนี้ และวิทยานิพนธ์ทุก ๆ เล่มที่ผมเข้าถึงได้ ก็เป็นแบบนี้)
  3. เนื้อสารบัญควรบอก บทที่ ชื่อบท และเลขหน้าของบทนั้น ๆ เริ่มตั้งแต่บทคัดย่อ จนไปจบที่ประวัติผู้เขียนเป็นรายการสุดท้าย ใช้อักษรแบบธรรมดาขนาด 14 พอยต์ (Normal 14 points)
  4. หัวข้อย่อยของแต่ละบทนั้น แสดงลึกไม่เกิน 1 ระดับ คือสารบัญจะแสดงรายละเอียดถึง 1.1 หมายถึง บทที่ 1 หัวข้อที่ 1 เท่านั้น จะไม่แสดงรายละเอียดถึง 1.1.1
  5. หัวข้อย่อยควรจัดให้ตรงกับบท (ไม่บังคับ แต่ตัวอย่างเป็นแบบนี้)
  6. เลขลำดับของหัวข้อย่อย จะมีหรือไม่มีก็ได้
  7. ระยะห่างระหว่างชื่อบท หรือหัวข้อสารบัญ ถึงบรรทัดแรกของสารบัญ ให้เว้น 2 บรรทัด (ของอักษรขนาดกี่พอยต์?)
ค้นไปค้นมา พบว่าไม่ต้องเขียนอะไรมาก เอา แพคเกจที่มีคนทำไว้แล้วมาใช้ก็ได้ แพคเกจที่หยิบมาใช้คือ titletoc ซึ่งติดตั้งมาพร้อมกับ titlesec ซึ่งอยู่ในแพคเกจเดเบียน texlive-latex-extra

สิ่งที่ต้องใช้ใน preemble ก็คือ เรียกคลาสที่จำเป็นขึ้นมา
\RequirePackage{titletoc}
\RequirePackage{ifthen}
\RequirePackage{lineno}

ตั้งค่าความลึกของหน้าสารบัญใหม่เป็น 1 (คือลงลึกแค่ชั้นเดียว) และตั้งค่าคำสั่ง \tableofcontents ใหม่
\setcounter{tocdepth}{1}
\renewcommand\tableofcontents{%
% Header of the first page of the TOC
\chapter*{\contentsname\@mkboth{\MakeUppercase\contentsname}
{\MakeUppercase\contentsname}}%
\begin{flushright}
\textbf{หน้า}
\end{flushright}

% Counter for tocitem
\newcounter{tocitem}
\setcounter{tocitem}{0}

% Turn on the linenumber counts, but do not want to display it.
\modulolinenumbers[50]
\linenumbers[1]
\@starttoc{toc}%
\setcounter{tocitem}{0}
\clearpage
}

สร้างคำสั่งใหม่สำหรับตรวจสอบว่าบรรทัดปัจจุบัน หรือ จำนวนหัวข้อที่แสดงในสารบัญเกินค่าทึ่กำหนดหรือยัง หากเกินแล้วให้ตัดขึ้นหน้าใหม่ รีเซตตัวนับ tocitem รีเซตตัวนับบรรทัดใหม่ และเขียนหัวของหน้าสารบัญใหม่ (เช่น สารบัญ (ต่อ) ในกรณีนี้)
\newcommand{\tocheadcont}[3]{
\ifthenelse{#1>32 \OR #2>32}{
%Should be a newpage here.
\pagebreak[4]
\resetlinenumber[1]
\setcounter{tocitem}{0}
\begin{ċenter}
{\Large \textbf{#3 (ต่อ)} }
\end{center} 
\begin{flushright}
\textbf{หน้า}
\end{flushright}
}{}
}

การจัดรายการสารบัญโดยใช้คำสั่ง \titlecontents จากแพคเกจ titletoc
% tocitem format for chapter
\titlecontents{chapter}[0mm]
{\stepcounter{tocitem}\tocheadcont{\thelinenumber}{\thetocitem}{สารบัญ}}
{\chaptername\hspace{1ex}\thecontentslabel\hspace{2mm}}
{}{\hfill \contentspage}

% tocitem format for section
\titlecontents{section}[0mm]
{\stepcounter{tocitem}\tocheadcont{\thelinenumber}{\thetocitem}{สารบัญ}}
{\hspace{\firstindentlength}\thecontentslabel\hspace{2mm}}{\hspace{\firstindentlength}\thecontentslabel\hspace{2mm}}
{\hfill \contentspage}

ผลลัพธ์ที่ได้แสดงในรูป


กล่าวโดยสรุปเราใช้
  • \titlecontents จากแพคเกจ titletoc เพื่อจัดรูปแบบของรายการสารบัญ
  • \thelinenumber จากแพคเกจ lineno เพื่อนับบรรทัดในหน้า
  • \newcounter{tocitem} สร้างตัวนับรายการสารบัญ
  • \ifthenelse จากแพคเกจ ifthen เพื่อตรวจเงื่อนไข
อันที่จริงเราอาจใช้ทางอื่นในการสร้างหัวสารบัญในหน้าถัดไปได้ เช่นเอาหัวสารบัญไปใส่ในส่วนหัวของหน้าแล้วจัด Margin ใหม่ก็ได้ แต่ผมไม่ได้คิดถึงทางออกนี้จนกระทั่งแก้ปัญหามาทางนี้เกือบเสร็จแล้ว หากใครมีทางเลือกอื่น ๆ เพื่อจัดหน้าสารบัญสำหรับวิทยานิพนธ์ ม.ข. ก็จะขอแบ่งประสบการณ์ด้วยครับ