Automatisch: Lokale PDFs umbennen nach BibTex-Key

Friedrich v. hinzugefügt 13 Monaten her
unbeantwortet

Hallo,

ich möchte gerne den folgenden Vorgang etwas ändern und automatisieren:


Bereits verknüpfte lokale Dateien umbenennen (https://www1.citavi.com/sub/manual5/de/automatically_renaming_files_attached_to_references_in_your_project.html)


Falls ein Titel eine verknüpften PDF-Datei besitzt, soll der alte Name der PDF-Datei durch den von Citavi gebildeten BibTex-Key (nicht Kurztitel) ersetzt werden. Dies soll per Skript/ Klick für alle Titel im Citavi-Projekt geschehen. Falls ein Titel mehrere verknüpfte PDF-Datei besitzt, soll einfach durchnummeriert werden. Optional/Wünschenswert: Falls ein Titel kein BibTex-Key hat, soll nichts geschehen, aber eine Liste solcher Titel in einer Hinweis-Box o.ä. ausgegeben werden, sodass die BibTex-Key geg. erzeugt werden können.

Das geht natürlich auch händisch, dauert aber bei vielen Titel lange. Ziel der Umbenennung: Wenn ich die PDFs im Explorer oder PDF-Viewer ohne Citavi ansehe, kann ich sie eindeutig einem Titel zuordnen. Außerdem kann ich so direkt sehen mit welchem BibTex-Key der Titel in Latex zitiert werden muss.


Ich habe im Forum gesucht, aber keine Lösung zu meinem Problem gefunden. Vielen Dank für Ihre Unterstützung!

Viele Grüße


Friedrich

Antworten (5)

Foto
2

Das sollte relativ einfach sein.

1. Ist das ein lokales Projekt oder ein Cloud-Projekt?

2. Ist garantiert, dass jeder Titel ein BibTex-Key hat, oder muss das Script auch für den Fall vorsorgen, dass ein Titel keinen BibTex-Key hat?

3. Welches Muster haben die Keys? Doppelpunkte etwa sind in Dateinamen ja nicht erlaubt.

Foto
1

Hallo SirPounce,


danke für deine Antwort!

1. Lokales Projekt

2. Wenn ich das richtig überblicke, hat gerade jeder Titel einen BibTex-Key. Trotzdem wäre es gut, wenn das abgefangen wird. Sonst müsste ich anderweitig den/die Titel ohne BibTex-Key finden, wenn das Skript nicht durchläuft.

3. Das Muster der Keys ist: [Autor, Herausgeber oder Institution][Jahr ermittelt]. Also keinen Doppelpunkt.


Vielen Dank für deine Hilfe!


Friedrich

Foto
2

Ich sehe jetzt erst, dass der Tag "Citavi 5" ist. Ich hoffe, das folgende Skript funktioniert dafür auch. Das Skript beruht auf einem, was mal im alten Citavi-Forum vom Support zur Verfügung gestellt wurde. Wenn der Bibtex-Key leer ist, wird der Titel einer Liste hinzugefügt, und am Ende wird diese Liste angezeigt. Anderenfalls wird der Anhang nach dem Bibtex-Key umbenannt, wenn es mehrere Anhänge gibt, werden diese durchnummeriert.


using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Net;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;

using SwissAcademic.Citavi;
using SwissAcademic.Citavi.Metadata;
using SwissAcademic.Citavi.Shell;
using SwissAcademic.Collections;

using System.Reflection;
using SwissAcademic.Citavi.Shell.Controls.Preview;

public static class CitaviMacro
{
	public static void Main()
	{
		if (Program.ProjectShells.Count == 0) return;		//no project open

		Program.ActiveProjectShell.PrimaryMainForm.PreviewControl.ShowNoPreview();
		
		List<Reference> references = Program.ActiveProjectShell.PrimaryMainForm.GetSelectedReferences();

		Project activeProject = Program.ActiveProjectShell.Project;
		string rootPath = activeProject.Addresses.AttachmentsFolderPath;

		//counter and list references where rename failed
		int renameCounter = 0;
		List<Reference> renamingFailed = new List<Reference>();

		foreach (Reference reference in references)
		{
			if (reference.Locations.Count == 0) continue;

			int i = 0;

			var locations = reference.Locations.ToList().Where(a => a.LocationType == LocationType.ElectronicAddress && a.Address.LinkedResourceType == LinkedResourceType.AttachmentFile);

			if (references.Count == 1) MessageBox.Show(locations.Count().ToString() + " attachments for the current reference");
			
			foreach (Location location in locations)
			{
				if (location == null) return;
				if (location.Address == null) continue;
				if (location.Address.UriString == null) continue;
				
				i = i + 1;
				
				FileInfo fileInfo = new FileInfo(rootPath + "\\" + location.Address.UriString);
				string fileExtension = fileInfo.Extension;
				if (fileExtension.Equals("pdf", StringComparison.InvariantCultureIgnoreCase)) continue;

				string newFileName = string.Empty;
				string newFullPath = string.Empty;
				string folderPath = string.Empty;
				
				string s = location.Address.UriString;
				int idx = s.LastIndexOf('/');

				if (idx != -1)
				{
				    folderPath = s.Substring(0, idx);
					folderPath = folderPath.Replace('/', '\\');
				}				
			
				try
				{
					if (!String.IsNullOrEmpty(reference.BibTeXKey))
					{
						newFileName = CleanString(reference.BibTeXKey);
					}
					else
					{
						renamingFailed.Add(reference);
						continue;
					}
					
				}
				catch (Exception e)
				{
				}

				if (locations.Count() > 1) newFileName += " (" + i.ToString() + ")";
				
				if (!string.IsNullOrEmpty(folderPath))
				{					
					newFullPath = rootPath + @"\" + folderPath + @"\" + newFileName + fileExtension;
				}
				{					
					newFullPath = rootPath + @"\" + newFileName + fileExtension;
				}
				string oldFullPath = rootPath + @"\" + location.Address.UriString;			
								
				if (!File.Exists(oldFullPath) && File.Exists(newFullPath))
				{
					System.IO.File.Move(newFullPath, oldFullPath);				

				}
				else if (File.Exists(newFullPath)) continue;

				try
				{
					location.Address.ChangeFilePathAsync(new System.Uri(newFullPath), AttachmentAction.Move);
					renameCounter++;
				}
				catch (Exception e)
				{
					MessageBox.Show("An error has occured while renaming " + location.Address + ":\n" + e.Message, "Citavi Macro", MessageBoxButtons.OK, MessageBoxIcon.Error);
					renamingFailed.Add(reference);
				}

			}// end foreach (Location location in reference.Locations)
		}// foreach (Reference reference in references)

		// Message upon completion
		string message = "{0} Locations have been renamed.";
		message = string.Format(message, renameCounter);

		if (renamingFailed.Count == 0)
		{
			MessageBox.Show(message, "Citavi Macro", MessageBoxButtons.OK, MessageBoxIcon.Information);
			return;
		}
		else
		{
			DialogResult showFailed = MessageBox.Show(message + "\n Would you like to show a selection of references where renaming has failed?", "Citavi Macro", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
			if (showFailed == DialogResult.Yes)
			{
				var filter = new ReferenceFilter(renamingFailed, "Renaming failed", false);
				Program.ActiveProjectShell.PrimaryMainForm.ReferenceEditorFilterSet.Filters.ReplaceBy(new List<ReferenceFilter> { filter });
				return;
			}
		}

		activeProject.SaveAsync();
	}
	private static string CleanString(string input)
	{
		char[] BAD_CHARS = new char[] { '?', '\\', '/', '?', '*', ':', '"', '“', '”', '‘', '’' };
		string output;
		output = input;
		output = RemoveDiacritics(output);
		output = output.Replace("  ", " ");
		output = string.Concat(output.Split(BAD_CHARS,StringSplitOptions.RemoveEmptyEntries));

		return output;
	}
	private static string RemoveDiacritics(string text)
	{
		var normalizedString = text.Normalize(NormalizationForm.FormD);
		var stringBuilder = new StringBuilder();

		foreach (var c in normalizedString)
		{
			var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
			if (unicodeCategory != UnicodeCategory.NonSpacingMark)
			{
				stringBuilder.Append(c);
			}
		}
		return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
	}
}

Foto
1

Genau ich nutze Citavi 5. Ich habe den Code in einem Beispiel-Dokument mit 4 Quellen ausprobiert.

Leider hat es nicht direkt funktioniert. Ich habe dir Screenshots der Fehlermeldungen mit angefügt.

Mir scheint, dass Variablen-Namen nicht passen/ definiert sind. Habe ich evtl. einen Schritt beim Nutzen des Makro-Editors vergessen?

Foto
1

Nein, das Problem ist wohl, dass die Methoden, welche Citavi bereitstellt, zwischen Citavi 5 und 6 geändert wurden. Ich gucke Mal, ob ich noch finden kann, wie die Methode in Citavi 5 funktionierte.

Antwort schreiben
 
Dateianlage anfügen (KEINE vertraulichen Dokumente!)