Is it possible to automatically pull in information from one note to another?

First, search the help docs and this forum. Maybe your question has been answered! The debugging steps can help, too. Still stuck? Delete this line and proceed.

What I’m trying to do

I want to set up a sequence of notes for content creation starting with a blog Post, then a podcast script and finally a newsletter set up.

The idea is the following:
The blog post starts with a H1 called “Summary” then a H1 called “Intro” then a H1 called “Main” and finally a H1 called “Conclusion”.
The podcast Script has the Headings: Summary, “Intro” and “Conclusion” where the information from the first note should be transferred once this Note is created.

Things I have tried

I tried to use perplexity to find the right code, as I am note a coder, but there are always parsing errors and after endless loops with perplexity it still wont work.

It would be really great if you had any idea as to how i could solve this problem. I also thought there might be a way using a dataview quiery but I just cant wrap my head around how this could work.

Your help would be greatly appreciated!

Here is the solution :slightly_smiling_face:

The query that will be placed in its own file

<%*
	async function getLastOpenFile(){
		const lastActiveFile = app.workspace.lastActiveFile;

		// If the last active file is different from the current one, then it can be used
		if (lastActiveFile !== null && lastActiveFile.basename !== tp.file.title ) {
			const lastActiveFileBaseName = lastActiveFile.basename;
			console.log(`No match on last active file, using it!. (${lastActiveFileBaseName} !== ${tp.file.title})`);

			await tp.file.move(`${lastActiveFile.parent.path}/${tp.file.title}`);

			return lastActiveFileBaseName;
		}

		// If it's the same, then in the history the last opened one can be retrieved.
		const lastFile = app.workspace.recentFileTracker.lastOpenFiles[0];
		const lastNameParts = lastFile.split("/");
		console.log( "Last active filed matched, using:", lastNameParts);
		const fileName = lastNameParts.pop();
		return fileName;
	}
-%>
```dataviewjs
const headerRegex = /^#+\s+(.*)$/;

// Function to find the nearest header above the query line number
function findNearestHeader(lines, lineNumber) {
    for (let i = lineNumber; i >= 0; i--) {
        const match = lines[i].match(headerRegex);
        if (match) {
            return match[1];
        }
    }
    return null;
}

// Manually set the unique ID for this query instance
const uniqueId = "<% await app.insertIncrementalId('GUID') %>";  // Replace "your_unique_id" with your manually set unique ID

// Set whether to show the "Go to the file" link
const showLink = (templater show link);  // Set to true or false based on your preference

// Get the current file path
const currentFilePath = dv.current().file.path;

// Load the content of the current file
dv.io.load(currentFilePath).then(currentFileContent => {
    if (!currentFileContent) {
        dv.paragraph(`Unable to read the current file content`);
        return;
    }

    const lines = currentFileContent.split('\n');

    // Find the line number of this query instance based on the unique identifier
    let queryLineNumber = null;
    for (let i = 0; i < lines.length; i++) {
        if (lines[i].includes(uniqueId)) {
            queryLineNumber = i;
            break;
        }
    }

    if (queryLineNumber === null) {
        dv.paragraph(`Unable to determine this query because there is a problem with this ID ${uniqueId}`);
        return;
    }

    const nearestHeader = findNearestHeader(lines, queryLineNumber);

    if (!nearestHeader) {
        dv.paragraph(`This query must be inside a header !`);
        return;
    }

    const targetFile = `<% getLastOpenFile() %>`;

    // Function to get content under the header in the target file
    async function getContentUnderHeader(targetFile, headerName) {
        const fileContent = await dv.io.load(targetFile);
        if (!fileContent) {
            dv.paragraph(`Unable to read the ${targetFile} content`);
            return null;
        }
        const targetLines = fileContent.split('\n');
        let headerFound = false;
        let content = [];

        for (const line of targetLines) {
            const match = line.match(headerRegex);
            if (match && match[1] === headerName) {
                headerFound = true;
                continue;
            }
            if (headerFound) {
                if (line.match(headerRegex)) break;
                content.push(line);
            }
        }

        return headerFound ? content.join('\n') : null;
    }

    getContentUnderHeader(targetFile, nearestHeader).then(content => {
        if (content) {
            dv.paragraph(content);
            if (showLink) {
                dv.paragraph(`[[${targetFile}#${nearestHeader} | Go to the file]]`);
            }
        } else {
            dv.paragraph(`The ${nearestHeader} header isn't in the targeted file `);
        }
    });

}).catch(err => {
    dv.paragraph(`Error loading the current file content for this query ` + err.message);
});

The query that will be placed in the note template under the header to which the information is to be transferred

<%*
if (typeof showLinkStore === 'undefined') {
    var showLinkStore = {};
}

var identifierNumber = Object.keys(showLinkStore).length + 1;
var currentShowLink = `showLink${identifierNumber}`;
var showContentKey = `content${identifierNumber}`;
showLinkStore[currentShowLink] = true; // Change this to 'false' if you don't want the link to show

showLinkStore[showContentKey] = await tp.file.include("[[Add link here]]");

if (showLinkStore[currentShowLink]) {
    tR += showLinkStore[showContentKey].replace("(templater show link)", "true");
} else {
    tR += showLinkStore[showContentKey].replace("(templater show link)", "false");
}
%>

The steps

  1. Install Incremental ID plugin from the community plugins.
  2. Enable the dataviewjs queries from the dataview plugin settings.
  3. Copy the first query and paste it in a new note.
  4. Copy the second query and paste it in the template note (in your case podcast template) under the header to which the information is to be transferred (in your case “Summary”, “Into” and “Conclusion”) then replace “Add link here” in the second pasted query with the name of the file that contains the first query.
  5. Create a new podcast note but with two conditions, the first is the creation of the note to which the information is to be transferred (in your case the podcast note) while opening the note from which the information is to be transferred (in your case the blog note), and the second condition is the presence of the header in which the query number 2 is located in the note from which the information is to be transferred (in your case the blog note), and their names are identical.

The result

Important Notes

  1. If you don’t want to show “Go to the file”, make showLinkStore[currentShowLink] = false; in the second query when you place it.
  2. You can paste the second query multiple times within a single file, and it will seamlessly display different data based on the header it is associated with. Additionally, you can adjust the show link value in some to control whether or not the link is displayed.
2 Likes

Wow :hushed:
Thank you!!!