6

I'm trying to draw an ERD diagram. I recycled code from a couple of posts around here and added my own spice, finally ending up with:


\documentclass[border=0.5in]{article}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}
\usepackage{scalefnt}
\usepackage{geometry}
\usepackage{pdflscape}

\makeatletter

\pgfarrowsdeclare{oone}{oone}
{
  \pgfarrowsleftextend{+0pt}%
  \pgfarrowsrightextend{+0pt}%
}
{
  \pgfutil@tempdima=0.25pt%
  \advance\pgfutil@tempdima by0.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
  \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfpathmoveto{\pgfqpoint{-12\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-12\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}

\pgfarrowsdeclare{one}{one}
{
  \pgfarrowsleftextend{+0pt}%
  \pgfarrowsrightextend{+0pt}%
}
{
  \pgfutil@tempdima=0.25pt%
  \advance\pgfutil@tempdima by0.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
    \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\pgfarrowsdeclare{many}{many}
{
  \pgfarrowsleftextend{+0pt}%
  \pgfarrowsrightextend{+0pt}%
}
{
  \pgfutil@tempdima=0.25pt%
  \advance\pgfutil@tempdima by0.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
    \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfpathmoveto{\pgfqpoint{-6\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-14\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
    \pgfpathmoveto{\pgfqpoint{-6\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-14\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}

\pgfarrowsdeclare{omany}{omany}
{
  \pgfarrowsleftextend{+0pt}%
  \pgfarrowsrightextend{+0pt}%
}
{
  \pgfutil@tempdima=0.25pt%
  \advance\pgfutil@tempdima by0.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
    \pgfpathmoveto{\pgfqpoint{0\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-8\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfpathmoveto{\pgfqpoint{-6\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-14\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
    \pgfpathmoveto{\pgfqpoint{-6\pgfutil@tempdima}{0\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-14\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
    \pgfpathmoveto{\pgfqpoint{-18\pgfutil@tempdima}{+8\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-18\pgfutil@tempdima}{-8\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\begin{document}


\tikzset{
    entity/.code={
        \tikzset{
            rounded corners,             
            name=#1,
            inner sep=2pt,
            every entity/.try,
            label=below:#1
        }%
        \def\entityname{#1}%
    },
    entity anchor/.style={matrix anchor=#1},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.20cm, inner ysep=0.075cm, anchor=west, text width=1in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    many to one/.style={
        many-one, zig zag to
    },
    one to omany/.style={
        one-omany, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}


\begin{landscape}

\scalefont{0.5}


\begin{tikzpicture}[every node/.style={font=\ttfamily}, node distance=0.5in]




\matrix [entity=Rent] {
    \properties{
        ID : int(11), 
        StartDate :  datetime,
        EndDate : datetime,
        PickupDate : datetime,
        ReturnDate : datetime,
        PickupMiles : int(11),
        ReturnMiles : int(11),
        Missing :  bool, 
        VehicleVIN  :  varchar(255),
        EmployeeUsername :  varchar(255),
        CustomerID :  int(11),
        DepartureGarage :  int(11),
        ArrivalGarage : int(11),
        OfferID : int(11),
        Kasko : bool,
        TPI :  bool, 
        CDW :  bool,
        TW  :  bool,
        DER :  bool,
        RestrictAge :  bool,
        ExtraMileageUnits :  int(11)      
    }
};

\matrix [entity=Employee, above=of Rent] {
    \properties{
        Username :  varchar(255),
        Password :  varchar(255),        
        Name :  varchar(255),
        LastName :  varchar(255)
    }
};

\matrix [entity=Vehicle, left= of Rent] {
    \properties{
    VIN : varchar(255),
    Plate : varchar(255),
    Seating : int(11),
    Doors : int(11),
    4WD : bool,
    Year : int(11),
    Diesel : bool,
    Displacement : double,
    Consumption : double,
    LPG : bool,
    ManualShift : bit,
    Autonomy : double,
    Discriminator : int(11),
    ModelID : int(11),
    HousedInGarage : int(11),
    Retired : bool,
    FullHybrid : bool,
    Mileage : int(11)
    }
};

\draw[one to omany] (Vehicle) to (Rent);
\draw[one-omany] (Employee) to (Rent);

\end{tikzpicture}
\end{landscape}

\end{document}

Now, I would like to have the label inside the node, maybe with a separator or something. ATM I get:

whatiget

But I would rather have:

enter image description here

Can anybody suggest a way to do so?

Thank you a whole lot.

  • Natuerlich I could do with a custom command to manually get what I want. The closest I've come is \def\mylabel#1{\node[]{#1};} And then \matrix [entity=Rent] { \mylabel {Rent}\\ \properties{ ... But it's ugly, very very ugly. – Tobia Tesan Aug 8 '14 at 11:52
6

I guess this is one way of doing it:

\documentclass[tikz,border=5]{standalone}

\usetikzlibrary{matrix}
\begin{document}
\tikzset{
    entity/.code={
        \tikzset{
            rounded corners,             
            name=#1,
            inner sep=2pt,
            every entity/.try,
        }%
        \def\entityname{#1}%
    },
    entity anchor/.style={matrix anchor=#1},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.20cm, inner ysep=0.075cm, anchor=west, text width=1.75in
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{\propertysplit#1;};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \gdef\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}
\def\propertysplit#1:#2;{#1:\hfill#2}

\def\entitynamenode{%
\node[every entity name/.try] (\entityname-name) {\entityname};
\draw (\entityname-name.south west) -- (\entityname-name.south east);
\\[1ex]
}
\tikzset{
  every entity name/.style={every property/.try, align=center}
}

\begin{tikzpicture}[every node/.style={font=\ttfamily}, node distance=0.5in]
\matrix [entity=Employee] {
    \entitynamenode
    \properties{
        Username :  varchar(255),
        Password :  varchar(255),        
        Name :  varchar(255),
        LastName :  varchar(255)
    }
};
\end{tikzpicture}   

\end{document}

enter image description here

  • Wonderful. You saved my life. – Tobia Tesan Aug 10 '14 at 16:34
  • Would you please be so kind as to explain what you've done a little? It's not entirely clear to me, especially \node[every entity name/.try] (\entityname-name) {\entityname}; and I wouldn't know what to Google. – Tobia Tesan Aug 10 '14 at 19:40
  • @mark-wibrow, is it possible to change the color of the box, too? – jackb Mar 26 '17 at 18:34
0

In the end I resorted to this little hack, which is not perfect not good for space saving, but does an acceptable job:

    entity/.code={
        \tikzset{
            rounded corners,             
            name=#1,
            inner sep=10pt,
            every entity/.try,
            label={[xshift=0cm, font=\bfseries, yshift=-10.5pt]#1}
        }%
        \def\entityname{#1}%
    }
    

I'm shifting the label inside the box and I'm adding enough padding to accomodate it.

However, besides being a bit ugly - it still gives me no separator.

This can certainly be improved upon by somebody who actually knows what she/he's doing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.